> For the complete documentation index, see [llms.txt](https://rocketmq-1.gitbook.io/rocketmq-connector/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://rocketmq-1.gitbook.io/rocketmq-connector/kai-fa-zhe-zhong-xin/zui-jia-shi-jian.md).

# 最佳实践

基于多次实践的总结

## 项目部署结构

为了方便添加维护，推荐用以下组织结构部署

* 将rocketmq与mongo等安装源码放于  `/usr/local/xxx`文件夹下,如以下样例

```bash
$ cd /usr/local/
$ ls 
....
maven  mongodb  mysql5.7  redis  rocketmq  rocketmq-externals 
```

* 通过启动参数配置日志到 `/opt/logs/` 文件夹下

```bash
#rocketmq 启动 rocketmq位置usr/local/rocketmq/rocketmq-4.5.2下
nohup sh ./bin/mqnamesrv >  /opt/rocketmq-4.5.2/logs/namesrvrun.log 2>&1 &
# 设置broker的部署方式，和日志位置
nohup sh ./bin/mqbroker -c ./conf/2m-2s-async/broker-a.properties -n "xxxx:9876" > /opt/rocketmq-4.5.2/logs/broker-a.log 2>&1 &

```

* 设置一个公用的`connector-plugins`目录,用于所有的connector包存放，如`/usr/local/rocketmq-external/connector-plugins`&#x20;

## Borker

#### &#x20;Broker 角色

​ Broker 角色分为 ASYNC\_MASTER（异步主机）、SYNC\_MASTER（同步主机）以及SLAVE（从机）。如果对消息的可靠性要求比较严格，可以采用 SYNC\_MASTER加SLAVE的部署方式。如果对消息可靠性要求不高，可以采用ASYNC\_MASTER加SLAVE的部署方式。如果只是测试方便，则可以选择仅ASYNC\_MASTER或仅SYNC\_MASTER的部署方式。

#### 3.2 FlushDiskType

​ SYNC\_FLUSH（同步刷新）相比于ASYNC\_FLUSH（异步处理）会损失很多性能，但是也更可靠，所以需要根据实际的业务场景做好权衡。

#### 3.3 Broker 配置

| 参数名                     | 默认值                       | 说明                                                                                                                  |
| ----------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| listenPort              | 10911                     | 接受客户端连接的监听端口                                                                                                        |
| namesrvAddr             | null                      | nameServer 地址                                                                                                       |
| brokerIP1               | 网卡的 InetAddress           | 当前 broker 监听的 IP                                                                                                    |
| brokerIP2               | 跟 brokerIP1 一样            | 存在主从 broker 时，如果在 broker 主节点上配置了 brokerIP2 属性，broker 从节点会连接主节点配置的 brokerIP2 进行同步                                    |
| brokerName              | null                      | broker 的名称                                                                                                          |
| brokerClusterName       | DefaultCluster            | 本 broker 所属的 Cluser 名称                                                                                              |
| brokerId                | 0                         | broker id, 0 表示 master, 其他的正整数表示 slave                                                                              |
| storePathCommitLog      | $HOME/store/commitlog/    | 存储 commit log 的路径                                                                                                   |
| storePathConsumerQueue  | $HOME/store/consumequeue/ | 存储 consume queue 的路径                                                                                                |
| mappedFileSizeCommitLog | 1024 \* 1024 \* 1024(1G)  | commit log 的映射文件大小                                                                                                  |
| deleteWhen              | 04                        | 在每天的什么时间删除已经超过文件保留时间的 commit log                                                                                    |
| fileReservedTime        | 72                        | 以小时计算的文件保留时间                                                                                                        |
| brokerRole              | ASYNC\_MASTER             | SYNC\_MASTER/ASYNC\_MASTER/SLAVE                                                                                    |
| flushDiskType           | ASYNC\_FLUSH              | SYNC\_FLUSH/ASYNC\_FLUSH SYNC\_FLUSH 模式下的 broker 保证在收到确认生产者之前将消息刷盘。ASYNC\_FLUSH 模式下的 broker 则利用刷盘一组消息的模式，可以取得更好的性能。 |

## NameServer

​RocketMQ 中，Name Servers 被设计用来做简单的路由管理。其职责包括：

* Brokers 定期向每个名称服务器注册路由数据。
* 名称服务器为客户端，包括生产者，消费者和命令行客户端提供最新的路由信息。​

## 消息幂等性

RocketMQ无法避免消息重复（Exactly-Once），所以如果业务对消费重复非常敏感，务必要在业务层面进行去重处理。可以借助关系数据库进行去重。首先需要确定消息的唯一键，可以是msgId，也可以是消息内容中的唯一标识字段，例如订单Id等。在消费之前判断唯一键是否在关系数据库中存在。如果不存在则插入，并消费，否则跳过。（实际过程要考虑原子性问题，判断是否存在可以尝试插入，如果报主键冲突，则插入失败，直接跳过）

msgId一定是全局唯一标识符，但是实际使用中，可能会存在相同的消息有两个不同msgId的情况（消费者主动重发、因客户端重投机制导致的重复等），这种情况就需要使业务字段进行重复消费。

## 参考连接

### [最佳实践](https://github.com/apache/rocketmq/blob/master/docs/cn/best_practice.md)
