网站策划书网站需求分析,毕设做网站,郑州防控升级,app网站建设源码前言
平时做后端开发时#xff0c;如果需要用到消息队列功能#xff0c;但公司的IT环境又没有提供专业的队列软件#xff08;RabitMQ/Kafka…#xff09;#xff0c;那么在简单且要求不高的场景下#xff0c;可以使用 Redis 的List数据类型来做消息队列。
但List类型有…前言
平时做后端开发时如果需要用到消息队列功能但公司的IT环境又没有提供专业的队列软件RabitMQ/Kafka…那么在简单且要求不高的场景下可以使用 Redis 的List数据类型来做消息队列。
但List类型有一个挺致命的缺点就是消息可靠性。当消费者使用 RPOP 命令从队列中取出一条消息后如果消费者在消费完成前崩溃了那么这条消息就永远丢失找不回来了。 注为了方便理解下文统一以“左进右出”的 List 作为例子 解决方案
下面介绍两种解决方案其中推荐方案2
方案1RPOPLPUSH
使用 RPOPLPUSH 命令从 List 里取出一条消息的同时又将这条消息写入另一个List例如
RPOPLPUSH myqueue myqueue:backup从 myqueue里取出一条消息同时写入到 myqueue:backup备份。
消息有了备份之后如果消费者程序中途崩溃了那么重启后只要首先检查备份队列有没有消息有的话优先消费备份队列的消息消费完后再消费主队列的消息就可以了。
但这样的设计只能防止一次程序崩溃如果在消费备份队列时消费者又崩溃了呢岂不是消息又丢失了难道又用同样的方法建一个myqueue:backup:2队列吗显然这样的方法很不优雅。 注RPOPLPUSH 命令自从 Redis 6.2.0 版本开始已经被标记为“过时”新的替代命令是 LMOVE 方案2LRANGE LTRIM
方案2是使用 LRANGE 和 LTRIM 命令LRANGE 命令可以一次性获取 N 条消息相比 RPOP命令一条条的取效率上要更高。等消息全部消费完毕后再使用 LTRIM 命令删除消息。这样在调用LTRIM命令前这批消息会一直都存在于队列中即使消费者崩溃也不会丢失。
示例 - 从队列右边取出100条数据然后删除
LRANGE myqueue -100 -1
LTRIM myqueue 0 -101myqueue是key名字后面两个数字是范围 start 和 stop0代表第一个元素-1代表最后一个元素-100代表倒数第100个元素如此类推。
需要注意的一点是对于“左进右出”的队列使用LRANGE获取的一批消息顺序是跟消费顺序相反的在消费前应先反转顺序。例如 [one, two, three, four] 四个元素使用 LRANGE myqueue -2 -1获取到的结果是 [three, four]但正确的消费顺序应该是 four - three
Stream数据类型
如果你使用的是 Redis 5.0 以上版本那么应该优先考虑使用 Stream 数据类型来做消息队列Stream相比List在功能上要强大得多提供了“消费者组”、“ACK确认”等消息队列场景专业功能有兴趣可以自行网上搜索学习。