首先要确定一个无可否认的事实,redis里的数据是易失的,所以用redis只是为了做到高性能的发布通知。 其次如下所说的只是简化版,极为简陋,但骨架子确实是能搭出来的
- 在数据库中建立一个消息表,有uuid,message,timestamp,is_used几个字段
- 每次往消息表推送一条消息后,把消息的uuid通过RPUSH指令推送到redis
- 取消息的进程使用BLPOP通过阻塞模式接收消息,收到uuid后从数据库的消息表里取出message进行后续操作,取的同时设置is_used = 1,或者可以根据业务,select for update那条消息,业务确实处理完成后再设置为1,这都是数据库本身的事,和redis的不可靠性无关
- redis可能因各种原因,丢失uuid,则需要一个独立的服务检测长时间未处理(timestamp > timeout and is_used = 0)的uuid,再次推送到redis中
接下来是一些QA
Q:如何解决重复推送uuid到redis中
A:redis只是为了协调分布式系统中多个组件,使其尽快处理消息,实际并发控制和防重复的控制在数据库
Q:一定要用uuid吗?
A:啥id都行,找到message就行了
Q:和postgres的queue有啥区别
A:用postgres自身的notify/listen和数据表实现的队列,一个监听服务就要开启一个数据库连接进程,如果监听的服务比较多,对数据库资源有点浪费。优势就是postgres的notify虽然也有瑕疵,但不会断电丢失。