> For the complete documentation index, see [llms.txt](https://darren.gitbook.io/project/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://darren.gitbook.io/project/devops/untitled/nsq-wen-ti-jie-da.md).

# nsq问题解答

**消费者如何通过lookupd找到话题**

nsqd在发起时，必须绑定到一个lookupd:

```
$ nsqd --lookupd-tcp-address=127.0.0.1:4160
1
```

也就说，消费者必须提前知道，他要的话题，被投递到了哪个nsqd上，可以通过对应的lookupd获取到该消息

**3 nsq怎么解决重复投递的问题**

很遗憾，nsq不能解决重复投递问题，需要客户端自己去处理。可以参考数据库唯一键，redis SETNX。不过前提是，消息本身具备一个唯一性的id

**nsq怎么解决执行顺序**

很遗憾，nsq同样不保证消息顺序。那么消费者如果有顺序需求，怎么办呢?\
解决方案: 标记消息权重，使用redis排行榜机制(zadd-添加,zrange-列表,zcard-长度,复杂度logN)

* 在消息中，增加标记头，头部包含以下信息:

```
{
    "total_number": 10,
    "number":1
}
1234
```

* 消费者在消费时

```
// 自带去重，不怕重复消费
conn.Do("ZADD", "话题名", number, "消息")

// 插入后检查长度
length ,_ := redis.Int64(conn.Do("ZCARD", "话题名"))

if length == total_number {
    messagss, _ := redis.Bytes(conn.Do("ZRANGE", "话题名",0, -1))
    // 按照messages顺序消费完。
    for i,v:=range message{
        handle(v)        
    }
}
// 最后，设置定期销毁该定序队列
// 该步不可忽视，因为可能出现单个消息重复投递，如果在消费完10个数据后，重复数据到达消费者这里，
// 那么该话题就会永久保留一个多余的消息，不会失效。
conn.Do("Expire", "话题名", 60 *60 * 24)
```

### nsqd挂了，消息会丢失吗?

默认配置下，会丢失，但是nsqd是可以配置成持久化的。

```
nsqd --lookupd-tcp-address=127.0.0.1:4160 --mem-queue-size 0
1
```

mem-queue-size设置成0后，则都会持久化，重启不会造成丢失。

### 工作方式总结 <a href="#id-85yie8" id="id-85yie8"></a>

* 生产者\
  生产者需要指定将消息写入哪个实例nsqd\
  当一个nsqd实例宕机时，生产者可以选择将消息写到其他的实例\
  生产者也可以将同一条消息写入两个nsqd（HA）
* nsqd\
  消息不会在nsqd之间传递，生产者把消息写到哪个nsqd就只能在该nsqd消费\
  不同的nsqd可以接收同一个生产者的相同的消息，参考生产者的说明\
  nsqd会将自己的服务信息广播给集群内的nsqlookupd
* 服务发现nsqlookupd\
  nsqlookupd与集群内的所有nsqd建立连接，检测实例的状态，并接收实例广播过来的服务注册\
  nsqlookupd接收消费者客户端的服务发现请求，将对应的实例返回给消费者（这里可以是多个实例）\
  一个集群可以有多个nsqlookupd
* 消费者comsumer\
  消费者可以与nsqd直连，但为了防止单点故障，不应该有这种固定的关系\
  官方推荐走服务发现nsqlookupd，参考生产者的说明，当一个nsqd宕机时，生产者可以将消息写入其他的nsqd，或者为了HA，生产者可以双写

```
支撑系统高可用的方案：

- 当一个nsqd宕机时，这台机上尚未消费且尚未落盘的消息会丢失；集群本身不提供副本和分片
- 鉴于上一条，对于幂等且不可丢失的消息，生产者可以选择双写，一条消息同时写两个实例
- 当正在写的nsqd宕机时，生产者可以选择写入其他的nsqd。前提是消费者通过nsqlookupd完成服务发现，及时感知集群的变化；或者消费者可以同时连上集群内所有的Nsqd实例
- 生产者可以做一定的负载均衡，将消息分散生产到不同的nsqd中
```

### 总结 <a href="#id-6rg1jf" id="id-6rg1jf"></a>

NSQ基本核心就是简单性，是一个简单的队列，这意味着它很容易进行故障推理和很容易发现bug。消费者可以自行处理故障事件而不会影响系统剩下的其余部分。

事实上，简单性是我们决定使用NSQ的首要因素，这方便与我们的许多其他软件一起维护，通过引入队列使我们得到了堪称完美的表现，通过队列甚至让我们增加了几个数量级的吞吐量。越来越多的consumer需要一套严格可靠性和顺序性保障，这已经超过了NSQ提供的简单功能。

对于相对比较敏感的消息，无法容忍某个nsqd宕机，或者磁盘无法使用的情况，简单性和可靠性似乎不能完全满足。就需要其他更适合业务的mq

参考文章

* <https://blog.csdn.net/fwhezfwhez/article/details/105411482>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://darren.gitbook.io/project/devops/untitled/nsq-wen-ti-jie-da.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
