Disque:Redis作者新开发的消息队列
程序员文章站
2022-03-07 19:20:55
...
[刘江/文]Redis的作者Salvatore Sanfilippo(网名Antirez)今天发表了一篇新博客文章,详细介绍了自己几个月以来在晚上和周末开发的新项目——Disque。这个项目今年1月份Antirez曾经在邮件列表中透露过,现在看来已经离正式发布不远了。
Disque是一个分布式的消息队列。与Redis有单结点和分布式模式不同,单一Disque结点也是只有一个结点的集群。它是一个AP系统,也就是具有Availability(可用性)和Partition tolerance(分区容错性)。另外它能在各种情形下保持高扩展性:无论是多生产者和多消费者处理多队列,还是所有生产者和消费者都在一个队列。
另外,Disque的设计中有一点重大牺牲,就是只尽力提供而不保证消息的排序。
Antirez还通过回答Adrian Colyer(AspectJ的作者,曾任SpringSource CTO,后来有人指出,Antirez记错了,这些问题是Jacques Chester提出的)在Hacker News上某次讨论(但这一讨论没有查到)中所提问题的方式,更详细地描述了Disque的特性:
开发初衷
Antirez之所以动念开发Disque,是因为看到很多人用Redis来处理队列,但这样做的优势和劣势都很明显:Redis很快、易用而且很多基础设施里已经在用;但是Redis的高可用性/集群特性的设计完全偏向可变数据结构,这与不可变的消息非常不同,并非最佳方案。
消息中介重要的功能是保证至少一次或者最多一次发送消息,而且前者更重要。Antirez开始想通过少量修改Redis来实现,但几天后发现客户端算法太复杂了。Redis已经有很多功能,再增加功能并非什么好主意。何况消息队列的运作方式与Redis很不同。
那么,是不是可以新开发一个消息队列呢?
世界上已经有很多消息队列了,新做一个有价值吗?Antirez想,既然有这么多人用Redis来处理消息队列,已有的方案看上去要么太简单要么太复杂,其中必有机会,于是他动手了。
开发过程
他头一次没有直接上来就写代码,而是花了几个星期思考设计,尝试从用户角度理解什么样的消息队列会让人更爽。主要的使用场景没变:延迟作业。Disque是通用系统,但主要针对的问题,是发送可能要处理的作业的消息。如果有什么违背了这一场景,就会被干掉。
设计有了,Antirez直接从Redis代码入手。幸运的是Redis部分就是编写C分布式系统的一个框架。协议、网络库、客户端处理、结点到结点的消息总线已经有了,无需重头再写。但他又不想影响Redis本身,于是采取了比较实际的办法:开一个Redis分支,然后将Redis专用的东西全部删掉,只剩一个框架,再开始实现设计。
到目前为止,他已经完成了80%左右的工作,还剩下AOF硬盘持久性没做,此外还需要对API做一些改善。
让我们期待他尽快放出代码吧。
Hacker News上Parse.ly的CTO Andrew Montalenti(@pixelmonkey )将Disque和Kafka做了比较:
Blekko的工程副总Chuck Mcmanis(@ChuckMcM)也给出了自己的经验:
本文来自刘江的博客。
Disque是一个分布式的消息队列。与Redis有单结点和分布式模式不同,单一Disque结点也是只有一个结点的集群。它是一个AP系统,也就是具有Availability(可用性)和Partition tolerance(分区容错性)。另外它能在各种情形下保持高扩展性:无论是多生产者和多消费者处理多队列,还是所有生产者和消费者都在一个队列。
另外,Disque的设计中有一点重大牺牲,就是只尽力提供而不保证消息的排序。
Antirez还通过回答Adrian Colyer(AspectJ的作者,曾任SpringSource CTO,后来有人指出,Antirez记错了,这些问题是Jacques Chester提出的)在Hacker News上某次讨论(但这一讨论没有查到)中所提问题的方式,更详细地描述了Disque的特性:
- 消息发送可以选择至少一次或者最多一次。
- 消息需要消费者确认。
- 如果没有确认,会一直重发,直至到期。确认信息会广播给拥有消息副本的所有结点,然后消息会被垃圾收集或者删除。
- 队列是持久的。
- Disque默认只运行在内存里,持久性是通过同步备份实现的。
- 队列为了保证最大吞吐量,不是全局一致的,但会尽力提供排序。
- 在压力大的时候,消息不会丢弃,但会拒绝新的消息。
- 消费者和生产者可以通过命令查看队列中的消息。
- 队列尽力提供FIFO。
- 一组master作为中介,客户端可以与任一结点通信。
- 中介有命名的队列,无需消费者和生产者干预。
- 消息发送是事务性的,保证集群中会有所需数量的副本。
- 消息接收不是事务性的。
- 消费者默认是接收时是阻塞的,但也可以选择查看新消息。
- 生产者在队列满时发新消息可以得到错误信息,也可以让集群异步地复制消息。
- 支持延迟作业,粒度是秒,最久可以长达数年。但需要消耗内存。
- 消费者和生产者可以连接不同的结点。
开发初衷
Antirez之所以动念开发Disque,是因为看到很多人用Redis来处理队列,但这样做的优势和劣势都很明显:Redis很快、易用而且很多基础设施里已经在用;但是Redis的高可用性/集群特性的设计完全偏向可变数据结构,这与不可变的消息非常不同,并非最佳方案。
消息中介重要的功能是保证至少一次或者最多一次发送消息,而且前者更重要。Antirez开始想通过少量修改Redis来实现,但几天后发现客户端算法太复杂了。Redis已经有很多功能,再增加功能并非什么好主意。何况消息队列的运作方式与Redis很不同。
那么,是不是可以新开发一个消息队列呢?
世界上已经有很多消息队列了,新做一个有价值吗?Antirez想,既然有这么多人用Redis来处理消息队列,已有的方案看上去要么太简单要么太复杂,其中必有机会,于是他动手了。
开发过程
他头一次没有直接上来就写代码,而是花了几个星期思考设计,尝试从用户角度理解什么样的消息队列会让人更爽。主要的使用场景没变:延迟作业。Disque是通用系统,但主要针对的问题,是发送可能要处理的作业的消息。如果有什么违背了这一场景,就会被干掉。
设计有了,Antirez直接从Redis代码入手。幸运的是Redis部分就是编写C分布式系统的一个框架。协议、网络库、客户端处理、结点到结点的消息总线已经有了,无需重头再写。但他又不想影响Redis本身,于是采取了比较实际的办法:开一个Redis分支,然后将Redis专用的东西全部删掉,只剩一个框架,再开始实现设计。
到目前为止,他已经完成了80%左右的工作,还剩下AOF硬盘持久性没做,此外还需要对API做一些改善。
让我们期待他尽快放出代码吧。
Hacker News上Parse.ly的CTO Andrew Montalenti(@pixelmonkey )将Disque和Kafka做了比较:
引用
设计上AP和部分排序都很类似。但Disque会在发送完成后垃圾收集数据,而Kafka在SLA/TTL中保持所有消息,允许重新处理。Disque在服务器端处理最多一次,而Kafka是由客户端处理的。
Blekko的工程副总Chuck Mcmanis(@ChuckMcM)也给出了自己的经验:
引用
开发这样的系统,我的建议是:永远不要依赖时间,总是假设至少一次,而且开发内置的错误检查和更正机制,这样在消息协议里有两个或者多个不变量违反时,可以从消息流中计算出正确结果。
本文来自刘江的博客。
上一篇: leetcode刷题笔记(0)
下一篇: NIO前世今生