使用jedis实现抢购功能,解决超发现象

抢购功能:在极短的时间内有大量的并发请求,出现因为并发所引起的问题。

实例:

一个商品100件,一个用户一次购买3件,100个用户同时购买。

使用redis的String类型实现:

通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃

第一种:String

   /*
     redis实现,String方式
   */
    public void redis(int num,int i){
        Jedis jedis = new JedisUtil().getJedis();
        try{
            jedis.watch("product");
            int stock = Integer.parseInt(jedis.get("product"));
            if (stock>=num){
                Transaction transaction = jedis.multi();
                transaction.decrBy("product",num);
                List<Object> result=transaction.exec();
                if (result!=null){
                    jedis.set("user::"+String.valueOf(i),"3");
                }
            }
        }finally {
            jedis.unwatch();
            jedis.close();
        }
    }

第二种:list

/*
      redis实现,String方式。
     */
    public void redisList(int num,int i){
        Jedis jedis = new JedisUtil().getJedis();
        try{
            jedis.watch("product");
           String product =jedis.lpop("product");
            if (product!=null){
                Transaction transaction = jedis.multi();
                List<Object> result=transaction.exec();
                if (result!=null){
                    jedis.set("user::"+String.valueOf(i),"1");
                }
            }
        }finally {
            jedis.unwatch();
            jedis.close();
        }
    }

使用redisTemplate实现:

因为redisTemplate.multi并没有开启一个事务,需要SessionCallback去执行,否则会报错:No ongoing transaction. Did you forget to call multi?

 @Autowired
    private RedisTemplate redisTemplate;
    /*
      不加金额简单测试了一下使用redisTemplate解决超发现象
       */
    @Override
    public void red(int redId, int userId) {
        int num = (int)redisTemplate.opsForHash().get("red","num");
        redisTemplate.watch("red");
        SessionCallback  sessionCallback = new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                if (num>0){
                    operations.multi();
                    operations.opsForHash().increment("red","num",-1);
                    List<Object> result = operations.exec();
                    if (result!=null){
                        operations.opsForHash().put("redId::"+redId,"userId::"+userId,"value");
                        System.out.println("用户:"+userId+"抢到了");
                        return true;
                    }
                }
                return null;
            }
        };
        redisTemplate.unwatch();
        redisTemplate.execute(sessionCallback);
    }

猜你喜欢

转载自blog.csdn.net/qq_39404258/article/details/107410901