赞
踩
redis的list可以用作队列,效率高,好用,但是有个缺点就是队列的时效性只能统一设置,一个list一个,要过期只能批量过期,不能达到只过旧的数据,新数据保留的情况。
网上解决方法是换成sring,每个单个项目单独设置ttl,不用list ,批量用keys + * 正则表表达式过滤,可以批量pos数据出来达到队列效果,但是redis官网上描述有keys只能用作debug模式,性能上会产生比较大的影响。
另一种解决方案就是采用多个list,分时间片段做队列,取队列优先按照到期时间近的队列取,队列分别过期方式,大概实现方法如下
规则:
(1) 设置两个list --> parta , partb
(2) 时限分为 2个区域 【总ttl】 = 【可写入】 + 【不可写入等待期】
比如: ttl = 48小时 , 写入list队列规则为 0~24 小时可写, 24~48 小时队列不再写入,等到ttl到期销毁 , ttl=24+24
(3)两个 parta , partb 分别轮流时间写入
创建parta--->写入parta队列--->parta到了等待期 ---> 创建partb 写入 ---->写入partb队列--->partb到了等待期---->创建parta写入(此时前一个parta应该已经销毁)
代码:
- long expire_a = redisUtil.getExpire(parta_list);
- long expire_b = redisUtil.getExpire(partb_list);
- //(24小时等待过期)
- long expire_out = 24;
- //两个分区时间间隔大小
- long expire = 24 * 2;
- if (expire_a > expire_out && expire_a>=expire_b-100) {
- //队列a还有剩余时间 ,且 a >= b (100秒作为误差)
- redisUtil.ListSet("parta", ob);//不设置ttl
- } else if (expire_b > expire_out && expire_a<=expire_b) {
- //队列b还有剩余时间 ,且 b >= a
- redisUtil.ListSet("partb", ob);//不设置ttl
- } else if ((expire_a < 0 && expire_b < 0) || (expire_a < 0 && expire_b <= expire_out))
- {
- //队列a ,b 不存在,新建队列a
- //队列a(a可能-1,-2)没有剩余时间且<0, 队列b没有剩余时间(b可能>0,=0,=-1,=-2),新建队列a
- redisUtil.ListSet("parta", ob, expire);//设置ttl
- } else if (expire_a <= expire_out && expire_b < 0) {
- //队列a(a可能-2,-1,0,>0)没有有剩余时间 且 队列b(b可能-2,-1)没有剩余时间且<0,新建队列b
- redisUtil.ListSet("partb", ob, expire);//设置ttl
- }
- else
- {
- //此处属于意外情况,理论上不存在,比如 a和b 几乎相同(不可能)
- //或者 a|b消亡一瞬间的,由于物理原因延迟几秒,还存在0状况,或未被及时销毁不为-2 ,造成 a|b 两个不可写入时间重叠,两个都无法写入
- //谁剩余时间大,写谁,不设置ttl
- if (expire_a >= expire_b)
- redisUtil.ListSet("parta", ob);//不设置ttl;
- else
- redisUtil.ListSet("partb", ob);//不设置ttl
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。