最佳实践

基于多次实践的总结

项目部署结构

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

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

$ cd /usr/local/
$ ls 
....
maven  mongodb  mysql5.7  redis  rocketmq  rocketmq-externals 
  • 通过启动参数配置日志到 /opt/logs/ 文件夹下

#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

Borker

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的情况(消费者主动重发、因客户端重投机制导致的重复等),这种情况就需要使业务字段进行重复消费。

参考连接

Last updated