Redis 怎么做消息队列?

有个想法,用两个服务器,node处理请求,把数据全部push到 redis缓存队列中,另一个php服务器不断的pop这个队列里的数据然后与mysql交…
关注者
1,945
被浏览
868,590
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

RPOPLPUSH - Redis

模式:可靠的队列(reliable queue)

Redis的列表(list)经常被用作队列(queue),用于在不同程序之间有序地交换消息(message).一个客户端通过LPUSH命令将消息放入队列中,而另一个客户端通过RPOP或者BRPOP命令取出队列中等待时间最长的消息.不幸的是,上面的队列方法是不可靠的.因为在这个过程中,一个客户端可能在取出一个消息之后崩溃,而未处理完的消息也就因此丢失.

使用RPOPLPUSH命令(或者它的阻塞版本BRPOPLPUSH)可以解决这个问题:
因为它不仅返回一个消息,同时还将这个消息添加到另一个备份列表当中.如果一切正常的话,当一个客户端完成某个消息的处理之后,可以用LREM命令将这个消息从备份列表删除.最后,添加一个客户端专门用于监视备份列表,它自动地将超过一定处理时限的消息RPOPLPUSH重新放入队列中去.因为负责处理该消息的客户端可能已经崩溃,这样就不会丢失任何消息了.

上述做法需要注意的问题:
RPOPLPUSH重新入队,即把备份列表右侧元素(表尾)重新入队,可能会出现消息被重复消费的情况.
因此消费操作要实现幂等性,即保证重复消费结果一致.


举例说明:

数据列表(source): c,b,a

2个客户端先后RPOPLPUSH消费并备份了2个元素:a和b

客户端1: RPOPLPUSH source backup (返回a并备份到backup)

客户端2: RPOPLPUSH source backup (返回b并备份到backup)

备份列表(backup): b,a

客户端消费逻辑完成后,删除备份列表的元素.

客户端1: LREM backup -1 a (移除备份列表backup中,从表尾到表头,第一个a,其中-1表示从表尾开始)

客户端2: LREM backup -1 b (移除备份列表backup中,从表尾到表头,第一个b,其中-1表示从表尾开始)


最后,Redis AOF持久化有几个配置:

appendfsync always 表示每当Redis执行写命令,就立即调用fsync把数据写入aof文件,最安全,但速度最慢.

appendfsync everysec 表示每秒钟fsync写一次,也就是有丢失前1秒数据的风险,但性能要比实时写入好得多,是默认配置.

appendfsync no 表示不调用fsync刷写,让操作系统自动刷新数据到磁盘(周期大概为30秒),快速但不够安全,不推荐.注意,Kafka的默认配置就类似这个级别.

性能与安全,自行权衡.