基于redis事件驱动实现延时队列

1,193 阅读3分钟

基于redis事件驱动实现延时队列

将redis的set跟expire事件写入list

使用方法

先进行clone本项目

git clone https://github.com/zzh787272581/redis_notifylist.git

进入目录

cd redis_notifylist

然后进行make 操作即可

本代码是基于redis最新release版本6.0.8来做,暂时未做其他适配

生成完成后,在redis启动后进行module的加载, 动态加载命令:


MODULE load /Users/zzh/c_code/redis-6.0.8/src/modules/notifylist.so

redis.conf加载模块配置

loadmodule /path/to/notifylist.so

项目背景:

在redis的订阅过程中,出现消息丢失后,没办法再找回,目前我们项目使用的是终端在线离线,一个事件过来消息丢失后,目前没有补救措施。

解决方案:

  1. 基于订阅方式本来对于在线离线是最好的解决方案,但是对于丢失后无法再找回,这是项目无法接受的,看了源码后,其实发生主要是终端在订阅过程中出现连接断开,导致消息未及时收到客户端,导致事件丢失。
  2. 基于低一点,我们可以考虑就是能否将数据直接在服务端基于事件的维度写到redis服务器上,由客户端来定时去拉取维护呢?答案是当然可以的,但是本次改完后,那就不是消息订阅了,而是事件通知机制了,这个本事redis module里面是支持的,主体核心思想就是,在模块加载的时候,进行事件订阅,然后有事件过来的时候,可以主动的触发,然后写入对应的list(当然也可以写到其他地方,比如set)。
  3. 这样在消费者这里就变成一个消息队列模式了,消费者去拉取即可。

命令:

新增一个命令:notifylist.set notifylist.set aa_* aa_list 第一个参数是需要订阅的key,可以是aa_1(常量key),也可以是aa_*(模块key) 第二个参数是需要写入的list名称,这个在后面消费者直接写入即可。

127.0.0.1:16378> notifylist.set aa_* aa_list
OK
127.0.0.1:16378> setex aa_3 10 1
OK
127.0.0.1:16378> setex aa_3 10 1
OK
127.0.0.1:16378> setex aa_3 10 1
OK
127.0.0.1:16378> setex aa_1 10 1
OK
127.0.0.1:16378> setex aa_2 10 1
OK
127.0.0.1:16378> setex aa_3 10 1
OK
127.0.0.1:16378> setex aa_3 10 1
OK
127.0.0.1:16378> setex aa_4 10 1
OK
127.0.0.1:16378> setex aa_5 10 1

对应的操作信息

1600586220.486773 [0 127.0.0.1:56813] "notifylist.set" "aa_*" "aa_list"
1600586222.862617 [0 127.0.0.1:56813] "set" "aa_1" "1" "ex" "5"
1600586222.862659 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"set\"}"
1600586227.954931 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"expired\"}"
1600586231.790095 [0 127.0.0.1:56813] "set" "aa_1" "1" "ex" "5"
1600586236.819905 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"expired\"}"
1600586240.149878 [0 127.0.0.1:56813] "set" "aa_1" "1" "ex" "5"
1600586279.909002 [0 127.0.0.1:56813] "set" "aa_1" "1" "ex" "5"
1600586279.909024 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"set\"}"
1600586284.992104 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"expired\"}"
1600586289.475982 [0 127.0.0.1:56813] "set" "aa_1" "1" "ex" "5"
1600586294.562344 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"expired\"}"
1600586301.236010 [0 127.0.0.1:56813] "setex" "aa_2" "5" "1"
1600586306.267347 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_2\",\"op\":\"expired\"}"
1600586334.042883 [0 127.0.0.1:56813] "setex" "aa_2" "10" "1"
1600586344.057793 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_2\",\"op\":\"expired\"}"
1600586519.852588 [0 127.0.0.1:56813] "setex" "aa_2" "10" "1"
1600586527.703180 [0 127.0.0.1:56813] "notifylist.set" "aa_*" "aa_list"
1600586529.964333 [0 127.0.0.1:56813] "notifylist.set" "aa_*" "aa_list"
1600586531.548331 [0 127.0.0.1:56813] "setex" "aa_2" "10" "1"
1600586531.548365 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_2\",\"op\":\"set\"}"
1600586541.626058 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_2\",\"op\":\"expired\"}"
1600586545.788009 [0 127.0.0.1:56813] "setex" "aa_1" "10" "1"
1600586555.810925 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"expired\"}"
1600586718.638267 [0 127.0.0.1:56813] "notifylist.set" "aa_*" "aa_list"
1600586721.920176 [0 127.0.0.1:56813] "setex" "aa_2" "10" "1"
1600586721.920238 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_2\",\"op\":\"set\"}"
1600586887.552270 [0 127.0.0.1:56813] "notifylist.set" "aa_*" "aa_list"
1600586888.752402 [0 127.0.0.1:56813] "setex" "aa_2" "10" "1"
1600586898.851083 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_2\",\"op\":\"expired\"}"
1600586918.566866 [0 127.0.0.1:56813] "setex" "aa_1" "10" "1"
1600586918.566937 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"set\"}"
1600586928.660138 [0 ?:0] "RPUSH" "aa_list" "{\"key\":\"aa_1\",\"op\":\"expired\"}"
1600587106.608993 [0 127.0.0.1:56813] "notifylist.set" "aa_*" "aa_list"