redis中对原子操作类AtomicInteger替代
- 操作的对象注意是数字类型的
- incr递增1并返回递增后的结果;
- incrby根据指定值做递增或递减操作并返回递增或递减后的结果(incrby递增或递减取决于传入值的正负);
- decr递减1并返回递减后的结果;
- decrby根据指定值做递增或递减操作并返回递增或递减后的结果(decrby递增或递减取决于传入值的正负);
消费线程参数由系统的原子类改为redis的key
注意一点这里的redis客户端为新启的一个,因为限流那里用了事务,可能会导致这里崩掉,后续有时间了再在这里补充吧
/** * 消费测试 * @param key 队列名称 * @param count 消费多少笔数据 * @param isEnd 活动是否结束 */ public void consumeTestRedis(String key,String count,String isEnd) 复制代码
效果图
网络异常,图片无法展示
|
对于消费还缺失防止刷单
请求频率的问题
一个用户5s内只准访问提交一次
- 法1 对于用户ID和消费物品设置个key过期时间为5s,key存在则说明以进行了消费,不存在放行
- 法2 利用有序集合和事务进行控制,下面是jedis的实现例子,也可以参考之前写的:限流和单元测试的例子
/** * @param key 限流 * @param maxAllow 最大允许 * @param time 间隔时间毫秒 * @return */ public boolean isRateAllow(Jedis jedis,String key,int maxAllow,long time) { Transaction transaction=jedis.multi(); long currentTime=System.currentTimeMillis(); //添加请求 transaction.zadd(key,currentTime,currentTime+":"+Thread.currentThread().getName()); //移除到这段时间差的请求 transaction.zremrangeByScore(key, 0,currentTime-time); //统计当前的请求数量 transaction.zcard(key); List<Object> result=transaction.exec(); Long size=(Long)result.get(2); System.out.println(result+" "+Thread.currentThread().getName()+":"+size); return size<=maxAllow; } 复制代码
限流后效果
网络异常,图片无法展示
|
注意!这里有个问题就是事务控制可能客户端不是串行的时候会报错,需要单独实例化个客户端
- 法3使用组件 Redis-Cell
消费个数的问题
- 可以为这个用户维护个计数器,key 物品id+用户id
效果大概如下
网络异常,图片无法展示
|