Redis如何实现一个消息队列 如何是实现延时队列 既然redis可以实现队列,为什么还需要mq消息队列

   如果你的业务需求足够简单,想把 Redis 当作队列来使用,肯定最先想到的就是使用 List 这个数据类型。因为 List 底层的实现就是一个「链表」,在头部和尾部操作元素,时间复杂度都是 O(1),这意味着它非常符合消息队列的模型如果把 List 当作队列,你可以这么来用。

生产者使用 LPUSH 发布消息:


图片.png

消费者这一侧,使用 RPOP 拉取消息:


图片.png

这个模型非常简单,也很容易理解。

图片.png

它可以支持多个生产者和多个消费者并发进出消息,每个消费者拿到的消息都
是不同的列表元素

延时队列得实现
延时队列可以通过 Redis 的 zset (有序列表)来实现。我们将消息序列化成一个字符串作为 zset 的 value,这个消息的到期处理时间作为 score,然后用多个线程轮询zset 获取到期的任务进行处理 。多个结程是为了保障可用性,万一挂了一个线程还有其他线程可以继续处理。因为有多个线程,所以需要考虑并发争抢任务,确保任务不会被多次执行。

伪代码后期实现

延时队列的应用
延时队列( Delayed Job)在项目中应该经常会使用到,比如用户下单超过30分钟没有支付,后台就自动取消订单;再比如新用户注册后,要求10分钟后给用户发一封邮件。这些需求都需要通过延时队列实现。

既然redis可以实现队列,为什么还需要mq消息队列?
与专业的消息队列对比,其实,一个专业的消息队列,必须要做到两大块:
消息不丢
消息可堆积

这里我们换个角度,从一个消息队列的【使用模型】来分析下,才能保证数据不丢失?使用一个消息队列,分为三大块:生产者,队列中间件,消费者

图片.png

1、生产者会不会丢消息?
2、消费者会不会丢消息?
3、队列中间件会不会丢消息?

  1. 生产者会不会丢消息?
  1. 当生产者在发布消息时,可能发生以下异常情况:
    消息没发出去:网络故障或其它问题导致发布失败,[中间件]直接返回失败
  2. 不确定是否发布成功:网络问题导致发布超时,可能数据已发送成功,但读取响应结果超时了

如果是情况 1,消息根本没发出去,那么重新发一次就好了。
如果是情况 2,生产者没办法知道消息到底有没有发成功?所以,为了避免消息丢失,它也只能继续重试,直到发布成功为止。
生产者一般会设定一个最大重试次数,超过上限依旧失败,需要记录日志报警处理。也就是说,生产者为了避免消息丢失,只能采用失败重试的方式来处理。但发现没有?这也意味着消息可能会重复发送。是的,在使用消息队列时,要保证消息不丢,宁可重发,也不能丢弃。
那消费者这边,就需要多做一些逻辑了。
对于敏感业务,当消费者收到重复数据数据时,要设计幂等逻辑,保证业务的正确性。从这个角度来看,生产者会不会丢消息,取决于生产者对于异常情况的处理是否合理。所以,无论是 Redis 还是专业的队列中间件,生产者在这一点上都是可以保证消息不丢的。

  1. 消费者会不会丢消息?
    这种情况消费者拿到消息后,还没处理完成,就异常宕机了,那消费者还能否重新消费失败的消息?
    要解决这个问题,消费者在处理完消息后,必须「告知」队列中间件,队列中间件才会把标记已处理,否则仍旧把这些数据发给消费者。
    这种方案需要消费者和中间件互相配合,才能保证消费者这一侧的消息不丢。
    无论是 Redis 的 Stream,还是专业的队列中间件,例如 RabbitMQ、Kafka,其实都是这么做的。
    所以,从这个角度来看,Redis 也是合格的。
  2. 队列中间件会不会丢消息?
    前面 2 个问题都比较好处理,只要客户端和服务端配合好,就能保证生产端、消费端都不丢消息。但是,如果队列中间件本身就不可靠呢?
    毕竟生产者和消费这都依赖它,如果它不可靠,那么生产者和消费者无论怎么做,都无法保证数据不丢。
    在这个方面,Redis 其实没有达到要求。
    Redis 在以下 2 个场景下,都会导致数据丢失。
    1.AOF 持久化配置为每秒写盘,但这个写盘过程是异步的,Redis 宕机时会存在数据丢失的可能
    2.[主从复制]也是异步的,主从切换时,也存在丢失数据的可能(从库还未同步完成主库发来的数据,就被提成[主库]
    基于以上原因我们可以看到,Redis 本身的无法保证严格的数据完整性。

所以,如果把 Redis 当做消息队列,在这方面是有可能导致数据丢失的。

再来看那些专业的[消息队列中间件]是如何解决这个问题的?像 RabbitMQ 或 Kafka 这类专业的队列中间件,在使用时,一般是部署一个集群,生产者在发布消息时,队列中间件通常会写「多个节点」,以此保证消息的完整性。这样一来,即便其中一个节点挂了,也能保证集群的数据不丢失。

也正因为如此,RabbitMQ、Kafka在设计时也更复杂。毕竟,它们是专门针对队列场景设计的。但 Redis 的定位则不同,它的定位更多是当作缓存来用,它们两者在这个方面肯定是存在差异的。最后,我们来看消息积压怎么办?

  1. 消息积压怎么办?
    因为 Redis 的数据都存储在内存中,这就意味着一旦发生消息积压,则会导致 Redis 的内存持续增长,如果超过机器内存上限,就会面临被 OOM 的风险。所以,Redis 的 Stream 提供了可以指定队列最大长度的功能,就是为了避免这种情况发生。但 Kafka、RabbitMQ 这类消息队列就不一样了,它们的数据都会存储在磁盘上,磁盘的成本要比内存小得多,当消息积压时,无非就是多占用一些磁盘空间,相比于内存,在面对积压时也会更加「坦然」。
    综上,我们可以看到,把 Redis 当作队列来使用时,始终面临的 2 个问题:
    Redis 本身可能会丢数据
    面对消息积压,Redis 内存资源紧张
    到这里,Redis 是否可以用作队列,我想这个答案你应该会比较清晰了。
    如果你的业务场景足够简单,对于数据丢失不敏感,而且消息积压概率比较小的情况下,把 Redis 当作队列是完全可以的。
    而且,Redis 相比于 Kafka、RabbitMQ,部署和运维也更加轻量。如果你的业务场景对于数据丢失非常敏感,而且写入量非常大,消息积压时会占用很多的机器资源,那么我建议你使用专业的消息队列中间件。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271