Closed vieyahn2017 closed 6 years ago
golang实战-nsq集群入门与坑 http://blog.csdn.net/qq_26981997/article/details/56673522
Nsq分析和Kafka对比
NSQ的主要特点如下:
具有分布式且无单点故障的拓扑结构 支持水平扩展,在无中断情况下能够无缝地添加集群节点 低延迟的消息推送,参见官方提供的性能说明文档 消息投递到消费者不能保证顺序 具有组合式的负载均衡和多播形式的消息路由 既擅长处理面向流(高吞吐量)的工作负载,也擅长处理面向Job的(低吞吐量)工作负载 消息数据既可以存储于内存中,也可以存储在磁盘中 实现了生产者、消费者自动发现和消费者自动连接生产者,参见nsqlookupd 支持安全传输层协议(TLS),从而确保了消息传递的安全性 具有与数据格式无关的消息结构,支持JSON、Protocol Buffers、MsgPacek等消息格式 非常易于部署(几乎没有依赖)和配置(所有参数都可以通过命令行进行配置) 使用了简单的TCP协议且具有多种语言的客户端功能库 具有用于信息统计、管理员操作和实现生产者等的HTTP接口 为实时检测集成了统计数据收集器StatsD 具有强大的集群管理界面,参见nsqadmin
NSQ 由 3 个守护进程组成: nsqd 是接收、保存和传送消息到客户端的守护进程。 nsqlookupd 是管理的拓扑信息,维护着所有nsqd的状态,并提供了最终一致发现服务的守护进程。 nsqadmin 是一个 Web UI 来实时监控集群和执行各种管理任务。
Nsq通过Channel的概念实现是对Topic消息订阅还是分发(类似Kafka消费组的概念)。 消费者从Channel处订阅消息,如果有多个消费者订阅同一个Channel,Channel中的消息将被传递到一个随机的消费者;如果多个消费者分别订阅不同的Channel,则分别获得Topic里的消息。
图片标题
Nsq因为不提供消息堆积能力,消息消费完就会被清理掉,所以如果要实现订阅模式,需要消息推送到不同的channel,然后消费者再分别从不同的channel中获得数据。但是这样带来一个问题就是消息会被拷贝多份,导致内存占用较多。
每个topic维护3个主要goroutine:
第一个叫做 router,负责从传入的go-chan中读取新发布的消息,并存储到一个队列里(内存或硬盘)。
第二个,称为 messagePump, 它负责复制和推送消息到如上所述的channel中。
第三个负责 DiskQueue IO,用于把消息写入到磁盘。默认先写入到内存,当内存queue满后就会写入到文件。
另外,每一个channel维护2个时间优先级队列,用于延时和消息超时的处理(并有2个伴随goroutine来监视它们)。
并行化的改善是通过管理每个channel的数据结构来实现,而不是依靠go运行时的全局定时器。
注意:在内部,go运行时使用一个优先级队列和goroutine来管理定时器。它为整个time包(但不局限于)提供了支持。它通常不需要用户来管理时间优先级队列,但一定要记住,它是一个有锁的数据结构,有可能会影响 GOMAXPROCS>1 的性能。请参阅runtime/time.goc。
NSQ也有临时channel的概念。临时channel会丢弃溢出的消息(而不是写入到磁盘),当没有客户订阅后它就会消失。这是一个Go接口的完美用例。Topics和channels有一个的结构成员被声明为Backend接口,而不是一个具体的类型。一般的 topics和channels使用DiskQueue,而临时channel则使用了实现Backend接口的DummyBackendQueue。
说明:
Nsq不依赖于协调节点,NsqLookupd进程只是保证最终一致性,不像Kafka完全依赖ZK,并且ZK强一致性。最终一致性带来的好处是可用性的提升,即使所有的NsqLookupd进程都宕机,Nsq还是能独立工作。
都有Topic概念,但是Kafka的Topic是全局的,Nsq的Topic可以在任意节点上。即同一个集群中两个Nsq节点都可以有同样一个Topic。生产者可以随意发送到任一个节点从而生成Topic,消费者通过查询NsqLookupd得知拥有Topic的Nsq节点列表。 全局Topic就会导致一定程度的中心化,从而影响节点的数量与可扩展性。
从可扩展性上看, Kafka内部会在所有的Broker中选举一个Controller节点进行管理Topic分区的Leader变迁等状态变换,这样集群的节点数量就会一定程度限制在controller里面。而Nsq没有中心节点,理论上比Kafka能支持更多的节点。
从使用上看,Nsq生产者是直接访问Nsqd进程,还需要通过查询NsqLookupd去找到有哪些节点。而Kafak因为topic是全局的,客户端只需要与任意节点通讯,内部会找到真正topic所在broker,对用户透明。
3.2 存储对比
Nsq采用内存方式存储,消息首先存储在内存队列中,如果队列满再持久化到文件中。 Kafka是直接消息写磁盘,利用操作系统的pagecache和文件连续写的方式得到极快的性能。
存储方式 | Nsq | Kafka |
---|---|---|
工作方式 | 采用内存方式存储,消息首先存储在内存队列中,如果队列满再持久化到文件中 | Kafka是每个Topic的分区消息直接写磁盘,先写入操作系统的pagecache,然后再由操作系统后台刷盘 |
优点 | 消息存放到内存可以保证低时延,节点内可以达到微秒级并且时延稳定。 | 实现简单,消息直接持久化同时性能也因为文件连续写达到保证。 |
缺点 | 持久化能力很弱,掉电会导致丢失数据。当然也可以把内存队列设置为0,然后数据就到写入到文件中,但影响性能。 | 1. 如果要保证每条数据一写入马上落盘,Kafka的这种写入方式会导致磁盘IO很高,分区很多的时候,尤其明显。2. 由操作系统落盘尾时延不可控,甚至达到秒级别。 |
3.3 高可用对比
高可用 | Nsq | Kafka |
---|---|---|
工作方式 | 没有高可用,即Topic没有复制之类的方式。 | PacificA高可用算法,每个Topic的分区有多份副本,Leader副本负责读写,其他副本同步复制冗余数据 |
优点 | 部署简单 | 通过ISR定义同步副本,可以在可用性与可靠性之间平衡。 |
缺点 | 宕机服务不可用 | 高可靠同步复制方式,对性能影响较大(但更可靠)。 |
3.4 性能对比
参考博文:
http://3ms.huawei.com/hi/blog/11838_1584903.html
吞吐量:
http://image.hw3static.com/hi/showimage-18005263-11838-ab2f176573bdd59f579c11fd09713b41.jpg
时延:
http://image.hw3static.com/hi/staticimages/hi3msf/images/2016/1126/17/58395ba498e40.jpg
官方的 The official Python client library for NSQ https://github.com/nsqio/pynsq 基于tornado3.0
另有https://github.com/dsoprea/NsqSpinner A Python, gevent-based, no-reactor NSQ client.
基于gevent
nsq源码导读(1.1) nsq的核心nsqd http://blog.csdn.net/lucifd_ch/article/details/46764185