redis(二)实战之抢红包

redis(二)实战之抢红包

image.png

image.png

image.png

image.png

代码示例

生成红包的代码

 //初始化红包池:将红包信息转化为JSON并且存入到redis的队列中
    public static void createRedPost() throws InterruptedException {
        JedisPool jedisPool = new JedisPool(URI.create("http://192.168.71.128:6379"), 2000);
        Jedis jedis = jedisPool.getResource();
        //20个线程去初始化红包池
        final  CountDownLatch countDownLatch = new CountDownLatch(Constants.THREAD_COUNT);

        for (int i = 0; i < Constants.THREAD_COUNT; i ++){
            //类似于分页 用于计算每个线程分得红包id的范围
            final int page = i;
            Thread thread = new Thread(){
                public void run(){
                    //每个线程要分多少红包
                    int per = Constants.RED_PACK_COUNT / Constants.THREAD_COUNT;
                    JSONObject jsonObject = new JSONObject();
                    for (int j = page * per; j <= (page + 1) * per; j ++){
                        //设置红包id
                        jsonObject.put("id", "r_id" + j);
                        //设置红包金额
                        jsonObject.put("money", j);
                        //从左侧插入到redis列表中
                        jedis.lpush("redPackPool", jsonObject.toJSONString());
                    }
                    countDownLatch.countDown();
                }
            };
            thread.start();
        }
        countDownLatch.await();//所有线程处于等待状态
    }

抢红包--不使用Lua脚本

 /**
     * 模拟抢红包的操作
     */
    public static void getRedPack() throws Exception{
        final CountDownLatch latch = new CountDownLatch(Constants.THREAD_COUNT);
        for (int i = 0; i < Constants.THREAD_COUNT; i ++){//20个线程同时跑
            Thread thread = new Thread(){
              public void run(){
                  //拿到Jedis连接
                  Jedis jedis = new Jedis("192.168.71.128", 6379);
                  while (true){
                      //创建用户id
                      String userId = UUID.randomUUID().toString();
                      //抢红包eval 可以直接调用我们eval中的代码


                      //实现方式1 不使用LUA脚本
                       //判断用户是否已经抢过红包 如果抢过直接返回
                      Boolean exist = jedis.hexists(Constants.USER_RECORD_KEY, userId);
                      if(exist){
                          System.out.println("你已经抢过红包了");
                          break;
                      }

                      //判断红包池中红包的个数 如果没有直接返回
                      Long count = jedis.llen(Constants.RED_PACK_POOL_KEY);
                      if (count == 0){
                          System.out.println("你来晚了,红包都被抢光了");
                          break;
                      }
                      //红包池中有红包 用户将获得红包
                      String redPackJson = jedis.rpop(Constants.RED_PACK_POOL_KEY);
                      Map<String, String> redPack = JsonUtils.toMap(redPackJson, String.class, String.class);
                      //将用户信息与红包信息绑定
                      redPack.put("userId", userId);
                      //写回到redis的红包详情列表中
                      jedis.lpush(Constants.RED_PACK_DETAIL_KEY, redPack.toString());
                      //将用户id保存到用户列表中
                      jedis.hset(Constants.USER_RECORD_KEY, userId, "1");
                      System.out.println("用户:{" + userId + "}抢到了红包:{" + redPack.get("id") + "}");


                  }
                  latch.countDown();
              }
            };
            thread.start();
        }
        latch.await();
    }

抢红包--使用lua脚本

 /**
     * 模拟抢红包的操作
     */
    public static void getRedPack() throws Exception{
        final CountDownLatch latch = new CountDownLatch(Constants.THREAD_COUNT);
        for (int i = 0; i < Constants.THREAD_COUNT; i ++){//20个线程同时跑
            Thread thread = new Thread(){
              public void run(){
                  //拿到Jedis连接
                  Jedis jedis = new Jedis("192.168.71.128", 6379);
                  while (true){
                      //创建用户id
                      String userId = UUID.randomUUID().toString();
                      //抢红包eval 可以直接调用我们eval中的代码

                      //实现方式2 使用LUA脚本
                      Object obj = jedis.eval(Basic.getRedPackScript, 4, Constants.RED_PACK_POOL_KEY, Constants.RED_PACK_DETAIL_KEY, Constants.USER_RECORD_KEY, userId);
                      if (obj != null){
                          System.out.println("用户ID号" + userId + "抢到的红包详情是:" + obj);
                      }else {
                          if (jedis.llen(Constants.RED_PACK_POOL_KEY) == 0){
                              break;
                          }
                      }
                  }
                  latch.countDown();
              }
            };
            thread.start();
        }
        latch.await();
    }

image.png

存放lua脚本的Basic类

public class Basic {

    public static String getRedPackScript =
            "if redis.call('hexists', KEYS[3], KEYS[4]) ~= 0 then\n" +
                    "return nil\n" +
                    "else\n" +
                    //从红包池中取出一个小红包
                    "local redPack = redis.call('rpop', KEYS[1]);\n" +
                    //判断红包池的红包是否为空
                    "if redPack then\n" +
                    "local x = cjson.decode(redPack);\n" +
                    //将红包信息与用户Id绑定,表示该用户已抢到红包
                    "x['userId'] = KEYS[4];\n" +
                    "local re = cjson.encode(x);\n" +
                    //记录用户已经抢过userIdRecordKey
                    "redis.call('hset', KEYS[3], KEYS[4], '1');\n" +
                    //将抢红包的结果详情存入redPackDetailKey
                    "redis.call('lpush', KEYS[2], re);\n" +
                    "return re;\n" +
                    "end\n" +
                    "end\n"    +
                    "return nil";


}


评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×