1 消息队列的作用
- 解耦,将一个流程加入一层数据接口拆分成两个部分,上游专注通知,下游专注处理
- 缓冲,应对流量的突然上涨变更,消息队列有很好的缓冲削峰作用
- 异步,上游发送消息以后可以马上返回,处理工作交给下游进行
- 广播,让一个消息被多个下游进行处理
- 冗余,保存处理的消息,防止消息处理失败导致的数据丢失
2 NSQ
2.1 特性
- 消息默认不可持久化,虽然系统支持消息持久化存储在磁盘中(通过设置 –mem-queue-size 为零),不过默认情况下消息都在内存中
- 消息最少会被投递一次,假设成立于 nsqd 节点没有错误
- 消息无序,是由重新队列(requeues),内存和磁盘存储的混合导致的,实际上,节点间不会共享任何信息。它是相对的简单完成疏松队列
- 支持无 SPOF 的分布式拓扑,nsqd 和 nsqadmin 有一个节点故障不会影响到整个系统的正常运行
- 支持requeue,延迟消费机制
- 消息push给消费者
2.2 流程
单个nsqd可以有多个Topic,每个Topic又可以有多个Channel。Channel能够接收Topic所有消息的副本,从而实现了消息多播分发;而Channel上的每个消息被分发给它的订阅者,从而实现负载均衡,所有这些就组成了一个可以表示各种简单和复杂拓扑结构的强大框架。
3 Kafka
3.1 特性
- 存储上使用了顺序访问磁盘和零拷贝技术(将磁盘文件的数据复制到页面缓存中一次,然后将数据从页面缓存直接发送到网络中),使得其具有非常强大的吞吐性能
- 数据落磁盘,能够持久化,支持消息的重新消费
- 投递保证支持 at least one / at most one / exactly once
- Partition / Comsumer Group内保证消息有序
4 对比
4.1 存储
- NSQ 默认是把消息放到内存中,只有当队列里消息的数量超过–mem-queue-size配置的限制时,才会对消息进行持久化。
- Kafka 会把写到磁盘中进行持久化,并通过顺序读写磁盘来保障性能。持久化能够让Kafka做更多的事情:消息的重新消费(重置offset);让数据更加安全,不那么容易丢失。同时Kafka还通过partition的机制,对消息做了备份,进一步增强了消息的安全性。
4.2 推拉模型
- NSQ 使用的是推模型,推模型能够使得时延非常小,消息到了马上就能够推送给下游消费,但是下游消费能够无法控制,推送过快可能导致下游过载。
- Kafka 使用的拉模型,拉模型能够让消费者自己掌握节奏,但是这样轮询会让整个消费的时延增加,不过消息队列本身对时延的要求不是很大,这一点影响不是很大。
4.3 消息的顺序性
- NSQ 因为不能够把特性消息和消费者对应起来,所以无法实现消息的有序性。
- Kafka 因为消息在Partition中写入是有序的,同时一个Partition只能够被一个Consumer消费,这样就可能实现消息在Partition中的有序。自定义写入哪个Partition的规则能够让需要有序消费的相关消息都进入同一个Partition中被消费,这样达到”全局有序“