NSQ是基于Go语言的实时分布式消息平台,设计用以完成日均亿级的大规模消息服务,可以用于基于最终一致性的消息队列。
消息队列和最终一致性
消息队列是一种进程之间的通信方式,举例而言,当进程a想要给进程b发送消息时,可以先将消息发送至消息队列,此时a充当生产者,b连接到消息队列,作为消费者,在适当的时候消费掉这个消息。消息队列最大的好处就是进程间的解耦合。
最终一致性可以理解为一种软同步,消息队列的通信方式是异步的,消息从进程a发送过去,不能保证进程b的消费,但采取轮回等措施后,可以保证在最终的阶段,a发出的消息经过消息队列后被进程b完全消费。
NSQ的特点
- 支持实现高可用性,去中心化
- 消息传递的保障性
- 限定单个进程的内存占用(消息可以保存于磁盘)
- 简化生产者和消费者的配置
- 升级简易
- 高效率
NSQ的设计架构
NSQ主要有四个组件构成:nsqd,nsqlookupd,nsqadmin和utilities。接下来,逐一介绍每个组件的职责。
nsqd
单个nsqd实例设计用来同时处理多个“流”的数据。“流”也就是主题(topic),一个topic有一个多个channel。每个channel都是对应的topic全部消息的拷贝。参见下图nsqd:
图中显示了一个nsqd的工作流程图,可以看到其topic为'clicks',当消息“A”到达topic时,3个channel就会分别复制消息“A”,这种机制可以称之为消息的多路分发,就像广播一样,通过多个channel传给连接的host。一般而言,每个channel对应一个下游的消费topic的服务,可以用不同的名字区分,图中channel的对应名称分别为:'metrics','spam_analysis','archive'。
topics和channels都是独立缓存数据,防止消费者速率低下导致其他channel或topic的阻塞。
并且,一般地,一个channel会有多个client连接,如果这些client都准备好接收消息,消息将随机发给一个client,这样可以起到一个负载均衡的作用,看起来有点像反向代理服务器。参见上图nsqd,channel: 'metrics'连接了3个独立的consumer client,过来的消息随机分配,实现了该channel的负载均衡。
nsqlookupd
nsqlookupd是NSQ的一个助手进程,提供了字典式的查询服务。消费者可以通过nsqlookd查询他们感兴趣订阅的topic所对应的nsqd实例的地址。从配置层面上而言,这种方式解耦了消费者与生产者,两者都只需要与nsqlookupd通信,双方不需要直接绑定配置,减少了复杂度和维护成本。
在低水平下每个nsqd都与nsqlookd有着长期的通信,这样使得nsqd持续将自己的状态反映给nsqlookupd。这些状态数据由nsqlookupd发送给消费者,告知他们最新的nsqd的地址。对消费者而言,有一个HTTP/查询的终端可供轮回。
需要注意的是,nsqd和nsqlookupd两个守护进程设计为独立运行,独立的模块,不需要协调。
nsqadmin
nsqadmin设计用来方便查看,反思,管理集群的。它提供一个Web用户界面来浏览topic/channel/consumer的层次结构,并检查每一层的深度和其他关键性的统计信息。同时,他还支持一些管理命令,比如删除或者清空channel(当channel中消息认为可以被丢弃时)等。
utilities
顾名思义,utilities是一些便于常见功能和数据流自省的实用程序。比如官网上get_start例子上的nsq_file命令。
补充
NSQ作为消息队列,虽然能保证消息的准确送达,却不能保证消息到达的先后顺序,所以需要消息顺序性的功能选择其他MQ或者加上时间戳,自己编写后端的排序程序。
接触NSQ不久,只是使用过,理解不够全面,望高手指点。转载请注明,谢谢。