zoukankan      html  css  js  c++  java
  • 红包雨redis实战(已上线)

    需求:

    花5豪币 点一次 每天点击上限次数 每人中奖上限
    分享免费玩2次 分享只算一次成功 后面分享不增加次数
    奖品表code id 类型 豪币 券 不中


    概率可配置
    每天凌晨清除0点击数

    数据库表(完成)
    奖品表:
    ID
    productId //存券ID定死
    type //无奖品 豪币 卷
    chance 概率
    createTime
    createUser


    //抽奖算法 (完成)
    1、初始化奖池,插入抽奖奖品 sadd act:hash 奖品表ID:i
    2、抽取奖品
    3、获取判断
    4、清空奖池

    免费次数表://先查此表 有值且大于0先扣除并且不扣积分
    ID
    OPENID
    TIMES

    中奖记录表:
    ID
    OPENID
    INBH
    OUTHB
    YEAR
    MONTH
    DAY
    CREATETIME
    接口:出入豪币接口、 查询剩余豪币数接口、优惠券接口.
    属性配置文件
    点击上限
    花费豪币数
    中奖上限
    redis表:
    用户击数//每天凌晨重置 //扣积分
    redPacket:openid:click
    每人中奖上限
    redPacket:openid:limitWinHb

    微信签名方法

    @Path("/getSignature.do") 
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getSignatureMethod(@QueryParam("--") String xx){
    String appId = RedPacketRainConfig.sub_appid;//不会变更
    String code = appId + ";" + toUrl;//跳转链接即调用它的页面
    String wxtk = "wxtk";
    Date date = new Date();
    SimpleDateFormat format = new SimpleDateFormat("yyddMM");
    String dateKey = format.format(date);
    String key = wxtk + dateKey;
    String enCode = CryptoUtil.desEncode(key, code);

    HttpPost httpPost = null;
    CloseableHttpResponse response = null;
    CloseableHttpClient client = null;
    JSONObject resultParams = null;
    httpPost = new HttpPost("---");
    StringEntity entityParams = new StringEntity(enCode, "utf-8");
    httpPost.setEntity(entityParams);
    httpPost.setHeader("Content-Type", "text/plain;charset=UTF-8");
    RequestConfig requestConfig = RequestConfig.custom()
    .setConnectTimeout(10 * 1000)
    .setConnectionRequestTimeout(30 * 1000)
    .build();
    httpPost.setConfig(requestConfig);
    client = HttpClients.createDefault();
    try {
    response = client.execute(httpPost);
    if (response != null && response.getEntity() != null) {
    String notifyURLParam = XmlUtils.parseStream(response.getEntity().getContent());
    resultParams = JSON.parseObject(notifyURLParam);
    resultParams.put("appid", appId);
    }
    } catch (IOException e) {
    e.printStackTrace();
    }

    return resultParams.toJSONString();
    }

     代码实现:仅部分核心

    @Path("/limit.do")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String isLimit(@QueryParam("openid") String openid) {
    JSONObject object=new JSONObject();
    if(openid==null||"".equals(openid)){
    object.put("code","0");
    object.put("msg","未获取openid,请联系管理员或刷新页面!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    }
    try {
    int freeTimes = 0;
    ActRedpacketFreetimesModel actRedpackeFreetimesModel =actRedpacketFreetimesService.get(openid);
    //不存在则说明未分享过
    if(actRedpackeFreetimesModel!=null){
    freeTimes=Integer.parseInt(actRedpackeFreetimesModel.getFreetimes());
    }
    if(JedisUtil.hget("redPacketTimes",openid)==null) {
    JedisUtil.hset("redPacketTimes", openid, "0");
    }
    if(System.currentTimeMillis()>new SimpleDateFormat("yyyy-MM-dd").parse("2019-12-26").getTime()){
    object.put("code","0");
    object.put("msg","活动已到期不可请求!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    }
    if(freeTimes>0) {
    object.put("code","0");
    object.put("msg","");
    object.put("result","00");
    return JsonUtil.toJsonStr(object);
    }else {

    int click = Integer.parseInt(JedisUtil.hget("redPacketTimes", openid));
    //免费次数为0 并且点击数>=上限数 或者免费次数为空(未分享过) 并且点击数>=2
    boolean clickIsLimit = (click >= RedPacketRainConfig.limit_click);
    if ((freeTimes <= 0 && clickIsLimit)) {
    object.put("code", "0");
    object.put("msg", "已超出当日可玩次数!");
    object.put("result", "01");
    return JsonUtil.toJsonStr(object);
    }
    Float hb=0f;
    hb = actRedpacketHBService.returnHb(openid);
    if(hb<RedPacketRainConfig.cost_hb){
    object.put("code","0");
    object.put("msg","您的豪币不足!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    }
    }
    }catch (NotMemberException e){
    object.put("code", "1");
    object.put("msg", "非会员请先注册!");
    object.put("result", "02");
    return JsonUtil.toJsonStr(object);
    }
    catch (Exception e){

    e.printStackTrace();
    object.put("code", "1");
    object.put("msg", "系统异常,请联系管理!");
    object.put("result", "01");
    return JsonUtil.toJsonStr(object);
    }
    object.put("code","0");
    object.put("msg","");
    object.put("result","00");
    return JsonUtil.toJsonStr(object);

    }


    //红包雨核心算法接口
    // 00 成功 01 失败提示! 02 服务器异常!
    @Path("/code.do")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String redPacketCore(@QueryParam("openid") String openid) {
    JSONObject object=new JSONObject();
    if(openid==null||"".equals(openid)){
    object.put("code","1");
    object.put("msg","未获取openid,请联系管理员!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    }
    try {
    if(JedisUtil.hget("redPacketTimes",openid)==null) {
    JedisUtil.hset("redPacketTimes", openid, "0");
    }
    if(System.currentTimeMillis()>new SimpleDateFormat("yyyy-MM-dd").parse("2019-12-26").getTime()){
    object.put("code","0");
    object.put("msg","活动已到期不可请求!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    }
    } catch (ParseException e) {
    e.printStackTrace();
    }

    String clientId= UUID.randomUUID().toString()+":"+openid;
    long start =System.currentTimeMillis();
    //开定时器每天晚上12点清空del redPacketTimes 公用的hash 存红包
    //空为第一次玩 初始化值0
    if(JedisUtil.hget("redPacketTimes",openid)==null) {
    JedisUtil.hset("redPacketTimes", openid, "0");
    }
    if(JedisUtil.get("redPacketBigGiftTimes")==null) {//最大奖项当日上限制
    JedisUtil.set("redPacketBigGiftTimes","2");
    }
    //获取免费次数。若为空也设置为0
    int freeTimes = 0;
    ActRedpacketFreetimesModel actRedpackeFreetimesModel =actRedpacketFreetimesService.get(openid);
    //不存在则说明未分享过
    if(actRedpackeFreetimesModel!=null){
    freeTimes=Integer.parseInt(actRedpackeFreetimesModel.getFreetimes());
    }
    int click = Integer.parseInt(JedisUtil.hget("redPacketTimes",openid));
    //免费次数为0 并且点击数>=上限数 或者免费次数为空(未分享过) 并且点击数>=2
    boolean clickIsLimit=(click>= RedPacketRainConfig.limit_click);
    if((freeTimes<=0&&clickIsLimit)){
    object.put("code","0");
    object.put("msg","已超出当日可玩次数!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    }
    RLock redissonLock= redissonClient.getLock(clientId);
    Boolean bs=false;
    try {
    bs=redissonLock.tryLock(3,10, TimeUnit.SECONDS);
    logger.info("time:"+new Date()+"---openid:"+openid);
    System.out.println("time:"+new Date()+"---openid"+openid);
    //豪币余额接口
    Float hb=actRedpacketHBService.returnHb(openid);
    if(JedisUtil.get("isInit")==null) {
    JedisUtil.set("isInit", "0");
    }
    if("0".equals(JedisUtil.get("isInit"))) {
    System.out.println("初始化奖池");
    JedisUtil.del("redPacketGift");
    //初始化奖池
    List<ActRedpacketGiftModel> giftList = actRedpacketGiftService.getAll();
    //记录当前次数
    int k = 0;
    int stock = 0;
    for (int i = 0; i < giftList.size(); i++) {
    float chance = Float.parseFloat(giftList.get(i).getChance());
    int time = (int) (chance * 10000);
    //大奖,获取库存
    if("2".equals(giftList.get(i).getWintype())){
    //库存若为0则继续生成其他奖品
    if(giftList.get(i).getStock()<=0){
    continue;
    }
    }
    //概率乘10000 加入redis奖池
    for (int j = 0; j < time; j++) {
    k++;
    JedisUtil.sadd("redPacketGift", giftList.get(i).getId() + ":" + k);
    }
    }
    JedisUtil.set("isInit","1");
    }

    //用户这次没有获取到锁,点击数小于10或免费次数大于0 可抽情况下,返回繁忙
    //免费次数为0情况下
    if(freeTimes<=0) {
    //hb数小于需要消耗的豪币数
    if(hb<RedPacketRainConfig.cost_hb){
    object.put("code","0");
    object.put("msg","您的豪币不足!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    }
    if (!bs && click < RedPacketRainConfig.limit_click) {
    //没获取锁,点击数<10 不扣除豪币 不+次数 提示繁忙
    object.put("code","0");
    object.put("msg","服务繁忙,请稍后继续参与活动!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    } else if (!bs && click >= RedPacketRainConfig.limit_click) {
    //没获取锁,点击数超限 扣除豪币
    object.put("code","0");
    object.put("msg","已超出当日可玩次数!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    //System.out.println("线程:{},获取锁失败,商品已卖完"+Thread.currentThread().getName());
    } else {
    actRedpacketHBService.updateHb(openid,"0",RedPacketRainConfig.cost_hb.toString());
    System.out.println("扣除豪币:"+RedPacketRainConfig.cost_hb.toString());
    click = Integer.parseInt(JedisUtil.hget("redPacketTimes", openid));
    //-------------------------开始抽奖-------------------------------------
    int realClick = click + 1;
    JedisUtil.hset("redPacketTimes", openid, Integer.toString(realClick));
    String wingift=JedisUtil.srandmember("redPacketGift");
    //大奖限制逻辑
    ActRedpacketWingiftLogModel actRedpacketWingiftLogModel=new ActRedpacketWingiftLogModel();
    String[] strings=wingift.split(":");
    System.out.println(strings[0]);
    ActRedpacketGiftModel actRedpacketGiftModel=actRedpacketGiftService.get(strings[0]);
    int x=bigRule(actRedpacketGiftModel,wingift,strings);
    if(x==1){
    //重新生成奖品
    wingift=JedisUtil.srandmember("redPacketGift");
    strings=wingift.split(":");
    actRedpacketGiftModel=actRedpacketGiftService.get(strings[0]);
    }
    if("0".equals(actRedpacketGiftModel.getWintype())||"1".equals(actRedpacketGiftModel.getWintype())||"2".equals(actRedpacketGiftModel.getWintype())){
    actRedpacketHBService.sendCpn(openid,actRedpacketGiftModel.getProductid());
    }
    System.out.println("线程:{" + Thread.currentThread().getName() + "},获取锁成功,锁状态:{" + bs + "},用户已点击数:{" + realClick + "}," + "奖池奖品信息:{"+wingift+ "}");
    //大奖限制逻辑
    actRedpacketWingiftLogModel.setCostBH(RedPacketRainConfig.cost_hb);
    actRedpacketWingiftLogModel.setOpenId(openid);
    actRedpacketWingiftLogModel.setPrizeName(actRedpacketGiftModel.getPrizename());
    actRedpacketWingiftLogModel.setProductId(actRedpacketGiftModel.getProductid());
    actRedpacketWingiftLogModel.setWinType(actRedpacketGiftModel.getWintype());
    actRedpacketWingiftLogService.save(actRedpacketWingiftLogModel);
    object.put("code","0");
    object.put("msg","恭喜中奖");
    object.put("result","00");
    object.put("prizeName",actRedpacketGiftModel.getPrizename());
    object.put("winType",actRedpacketGiftModel.getWintype());
    //-------------------------抽奖结束----------------------------------
    //处理业务代码需要的时间 取奖品表 抽奖 获取奖项 判断 若为豪币判断是否超限制 调用接口 清空奖池
    }
    }else{
    //还有免费次数情况
    if (!bs) {
    object.put("code","0");
    object.put("msg","服务繁忙,请稍后继续参与活动!");
    object.put("result","01");
    return JsonUtil.toJsonStr(object);
    }else{//获取锁的其他情况 即可抽
    String wingift=JedisUtil.srandmember("redPacketGift");
    //大奖限制逻辑
    ActRedpacketWingiftLogModel actRedpacketWingiftLogModel=new ActRedpacketWingiftLogModel();
    String[] strings=wingift.split(":");
    ActRedpacketGiftModel actRedpacketGiftModel=actRedpacketGiftService.get(strings[0]);
    int x=bigRule(actRedpacketGiftModel,wingift,strings);
    if(x==1){
    //重新生成奖品
    wingift=JedisUtil.srandmember("redPacketGift");
    strings=wingift.split(":");
    actRedpacketGiftModel=actRedpacketGiftService.get(strings[0]);
    }

    if("0".equals(actRedpacketGiftModel.getWintype())||"1".equals(actRedpacketGiftModel.getWintype())||"2".equals(actRedpacketGiftModel.getWintype())){
    actRedpacketHBService.sendCpn(openid,actRedpacketGiftModel.getProductid());
    }
    //代码日志记录有误 花费0豪币
    //actRedpacketWingiftLogModel.setCostBH(0f);
    actRedpacketWingiftLogModel.setCostBH(RedPacketRainConfig.cost_hb);
    actRedpacketWingiftLogModel.setOpenId(openid);
    actRedpacketWingiftLogModel.setPrizeName(actRedpacketGiftModel.getPrizename());
    actRedpacketWingiftLogModel.setProductId(actRedpacketGiftModel.getProductid());
    actRedpacketWingiftLogModel.setWinType(actRedpacketGiftModel.getWintype());
    actRedpacketWingiftLogService.save(actRedpacketWingiftLogModel);
    System.out.println("线程:{" + Thread.currentThread().getName() + "},获取锁成功,锁状态:{" + bs + "}," + "奖池奖品信息:{"+wingift+ "}");
    freeTimes=Integer.parseInt(actRedpackeFreetimesModel.getFreetimes());
    int nowTimes = freeTimes - 1;
    actRedpacketFreetimesService.updateTimes(Integer.toString(nowTimes),openid);
    HashMap hashMap=new HashMap();
    object.put("code","0");
    object.put("msg","恭喜中奖");
    object.put("result","00");
    object.put("prizeName",actRedpacketGiftModel.getPrizename());
    object.put("winType",actRedpacketGiftModel.getWintype());
    //-------------------------抽奖结束----------------------------------
    }
    }
    //非注册会员
    }catch (NotMemberException e) {
    e.printStackTrace();
    object.put("msg","非注册会员");
    object.put("code","1");
    object.put("result","02");
    logger.error("NotMemberException:"+e.getMessage());
    //更新豪币失败
    }catch (UpdateHBException e) {
    e.printStackTrace();
    object.put("msg","豪币扣除失败,请稍后重新参与活动");
    object.put("code","1");
    object.put("result","02");
    logger.error("UpdateHBException:"+e.getMessage());
    }catch (SendCpnException e) {
    e.printStackTrace();
    object.put("msg","发送优惠券异常");
    object.put("code","1");
    object.put("result","02");
    logger.error("SendCpnException:"+e.getMessage());
    }catch (Exception e) {
    e.printStackTrace();
    object.put("msg","服务器异常,请联系管理员!");
    object.put("code","1");
    object.put("result","02");
    logger.error("Exception:"+e.getMessage());
    } finally {
    if(bs){
    redissonLock.unlock();
    }
    }
    long endTime =System.currentTimeMillis();
    System.out.println("执行一次请求时间:"+(endTime-start)+"毫秒");
    return JsonUtil.toJsonStr(object);

    }




    //分享获得免费次数接口
    @Path("/ftimes.do")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String shareFree(@QueryParam("openid") String openid){
    JSONObject object=new JSONObject();

    ActRedpacketFreetimesModel actRedpackeFreetimesModel =actRedpacketFreetimesService.get(openid);
    //未分享过
    if(actRedpackeFreetimesModel==null){
    object.put("code","0");
    object.put("msg","分享成功,获得2次游戏机会");
    actRedpacketFreetimesService.insertTimes(IdUtil.getFullId(),openid,RedPacketRainConfig.free_times,new Date());
    }else{
    object.put("code","0");
    object.put("msg","分享成功,已获得过2次机会");
    }
    return JsonUtil.toJsonStr(object);
    }

    //大奖规则 一天中奖上限2次
    public int bigRule(ActRedpacketGiftModel actRedpacketGiftModel,String wingift,String[] strings){
    int bigTimes=Integer.parseInt(JedisUtil.get("redPacketBigGiftTimes").toString());
    if("2".equals(actRedpacketGiftModel.getWintype())){
    //若上限次数小于等于0或者库存小于等于0,说明已达当日大奖中奖次数上限
    int bigStock=actRedpacketGiftModel.getStock();
    if(bigTimes<=0||bigStock<=0){
    //若为2说明已经移除大奖重新初始化奖池 备用方案 非万分一概率情况
    /*if(!"2".equals(JedisUtil.get("isInit"))) {
    logger.info("移除大奖,初始化奖池");
    JedisUtil.del("redPacketGift");
    //初始化奖池
    List<ActRedpacketGiftModel> giftList = actRedpacketGiftService.getAll();
    //记录当前次数
    int k = 0;
    int stock = 0;
    for (int i = 0; i < giftList.size(); i++) {
    float chance = Float.parseFloat(giftList.get(i).getChance());
    int time = (int) (chance * 10000);
    //大奖,获取库存
    if ("1".equals(giftList.get(i).getWintype())) {
    //库存若为0则继续生成其他奖品
    continue;
    }
    //概率乘10000 加入redis奖池
    for (int j = 0; j < time; j++) {
    k++;
    JedisUtil.sadd("redPacketGift", giftList.get(i).getId() + ":" + k);
    }
    }
    JedisUtil.set("isInit", "2");
    }*/
    //移除大奖
    JedisUtil.srem("redPacketGift",wingift);
    return 1;
    }else{
    //未大上限 扣除次数 扣除大奖库存
    int realBigTimes=bigTimes-1;
    JedisUtil.set("redPacketBigGiftTimes", Integer.toString(realBigTimes));
    bigStock=bigStock-1;
    actRedpacketGiftService.updateStock(strings[0],bigStock);
    return 0;
    }
    }else{
    return 0;
    }
    }

     以上代码需提前初始化红包奖池

  • 相关阅读:
    laravel中使用include和component方法中的一点小区别
    【解决】Converting circular structure to JSON
    NUXT中使用axios,自己项目测试记录
    iPhone“连到系统上的设备没有发挥作用”原因分析及解决方法 20200105
    vue-touch不能上下滑动的问题【解决】
    动态加载swiper,默认显示最后一个swiper-slide怎么办
    CentOS 7 修改开机等待时间
    使用IIS管理器搭建FTP服务器以及其启用虚拟主机名
    织梦后台删除子栏目不成功的解决方法
    去除织梦标签[field:image/]所产生的宽高
  • 原文地址:https://www.cnblogs.com/chenweida/p/12118728.html
Copyright © 2011-2022 走看看