Redis和DelayQueue设计具有过期时间的缓存


1、场景:

有一款APP,用户登陆后。会将用户的用户号,手机号、以及设备号等上报给后台的清洗程序(这里设备号是唯一的)。后台因为需要根据这三个做一定的运算。所以希望
对于每一个访客-用户关系进行缓存,并只缓存10分钟,并且缓存使用redis。注意,是每一条记录都只缓存10分钟。而不是一批记录!

2、解决方案
1、在redis里有个函数,hset(String key,String field ,String value),也有对应的hexpire(String key,int second),但是这里如果以设备号为key的话,
field和value要怎么设置??因为缓存进去后,因为我们取的时候是不知道设备号的,只能说一条记录10分钟到了,就应该从redis取出来。并删除redis的记录。
这里笔者还注意到有另一个函数,删除函数为hdel(String key,String ..fields).如果将设备号放到hset的field 字段,key为一个固定的字符串。但是还是那一个问题
怎么知道有一个设备号已缓存10分钟了?反复思考,想到Java的一个类,叫DelayQueue。就是它。

DelayQueue是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。我们可以将DelayQueue运用在以下应用场景:
其主要有以下两种使用场景:
缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。

注:
hset
描述:将哈希表key中的域field的值设为value。如果key不存在,一个新的哈希表被创建并进行HSET操作。如果域field已经存在于哈希表中,旧值将被覆盖。
参数:key field value
返回值:如果field是哈希表中的一个新建域,并且值设置成功,返回1。如果哈希表中域field已经存在且旧值已被新值覆盖,返回0。
hdel 
描述:删除指定的field
参数:key field:


3、编码设计

    上面的方案还要注意一点,进行缓存操作和删除缓存操作应该要在不同的线程。

这是strom的版本:

(1)延迟队列设计


(2)初始化函数



这里prepare在整个strom工程起来之后,只会执行一次,而execute只要会数据会一直不断执行。

然后是进行缓存操作:



删除访客记录的线程:


猜你喜欢

转载自blog.csdn.net/evankaka/article/details/54984451