nsq介绍

消息队列主要用来在高并发、大数据场景下解决服务的异步处理,流量削峰填谷,应用解耦问题,提高系统模块化能力。
市面上有很多优秀的消息队列产品,如Kafka、RabbitMQ、ActiveMQ、RocketMQ等,本文主要介绍下跟着golang一起流行起来的nsq。

nsq是基于go语言开发的一个实时分布式消息平台。

拓扑结构/核心组件

nsqd

nsqd是分布式中的单个节点,负责具体接收生产者消息,发布消息给客户端(Writer/Reader)。提供TCP和HTTP服务。

nsqlookupd

nsqlookupd负责服务发现,管理各个nsqd节点。同时提供TCP和HTTP服务。

TCP服务:nsqd作为客户端,会连接nsqlookupd的TCP服务,上报自己的topic和channel信息,nsqlookupd通过TCP服务对nsqd节点做心跳检测。

HTTP服务:客户端通过nsqlookupd来查询他们想消费的指定topic的对应nsqd节点的地址(生产者),然后进行直连nsq节点。

nsqadmin

负责实时监控集群和执行各种管理任务,提供简单的可视化管理界面

核心概念

topic

一个topic可以理解为是一个“消息类型”。

生产者通过调用HTTP API或者TCP客户端将消息发送给nsqd的指定topic上,如果该topic不存在,则由nsqd负责新建。

channel

一个channel可以理解为是一个具体的“消息队列”。
生产者每次发布消息时,消息会采用多播的方式全量复制到各个channel上。
一个channel可能会被多个消费者订阅,channel中的消息会被传递给随机的一个消费者,channel来负责多个消费者间的负载均衡,也就是说订阅同一个channel的所有消费者接收到的消息数据加起来就是该topic的全量数据。
综上,也就是说每一个channel都能接收到一个topic下的所有消息的拷贝,然后每个消费者接收到一个channel中消息的一部分。

channel会将消息进行排队,起到队列的作用,多个生产者生产的同一topic消息由连接该topic的channel负责排队。如果没有消费者来读取消息,消息首先会在内存中排队,当数量太多时就会被持久化到磁盘中。参数–mem-queue-size可以用来决定一个channel队列可保存在内存中的消息数量。

消费者通过TCP的方式来订阅自己需要的channel,如果该channel是消费者第一次订阅,就会创建这个channel。由此可见,topic和channel都不是预先设置的,而是在通信过程中动态创建的。

message

消息实体,生产者消费者通信的具体内容

通信流程

基本流程:生产者向一个nsqd节点推送message,消费者通过nsqlookupd连接到相应的nsqd节点上获取message。也就是说生产者消费者最终都是通过直连单个nsqd节点完成通信的。

总结

优点

部署极其简单,通过简单的配置就可直接使用,这是它的最大卖点。

缺点

  • 消息之间无法保证顺序
  • 多个nsqd节点之间没有消息复制,一个节点挂起,该topic消息就都挂了。
  • 消费者接收到的消息有可能是重复的(为了解决nsqd单点问题,生产者的每一个message都给所有nsqd发送一份,这样解决了nsqd单点故障问题,但消费者收到的消息是重复的)
  • 可能会丢失消息(其数据存储模型是先在内存,内存满了之后写入磁盘,如果机器宕机,内存中的消息就丢失了)
-------------本文结束 感谢您的阅读-------------