RocketMQ是什么?
Apache RocketMQ 是阿里开源的一款高性能、高吞吐量的消息队列,前身是MetaQ。
应用场景
以下是我整理的一些业务场景。
- 限流:秒杀系统,其他内部生产系统(如批量升级硬件固件版本,批量变更MySQL线上数据结构等),为系统提供消息堆积的能力
- 系统解耦:如把注册和发邮件拆为2个系统,注册后通过发送RocketMQ消息让邮件系统消费执行,加强系统扩展性
- 数据同步:如mysql binlog同步
- 延迟处理:如订单场景,需要自动删除用户30分钟内还没处理的数据,提供延迟队列,但只支持以下的时间设定,不过基本能满足大部分业务的需求。
1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h - 实时流计算处理(flink)
RocketMQ组件
- NameServer:服务发现
- Producer:生产者
- Broker:中转器
- Consumer:消费者
主要工作流程:
- NameServer启动
- Broker启动注册到NameServer,NameServer存储了topic对应的队列信息,队列信息里面包含Broker机器关联(对应的源码对象名是QueueData),也就是NameServer维护了topic和Broker机器的映射关系
- Producer,Consumer从NameServer拉取Topic路由信息
- Producer发送信息到指定topic,会判断是否存在该topic
- Consumer拉取监听的topic信息进行消费
RocketMQ有这么多组件,有没有可视化界面进行运维呢?有的。https://github.com/apache/rocketmq-externals 这里有个rocketmq-console项目。
谈谈队列
死信队列:
当一条消息初次消费失败,会自动进行消息重试;达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。
逻辑队列(consume queue):
tip:commitLog是存放物理文件,存储具体消息内容。
逻辑队列用来存储消息在commitLog中的位置,不存储实际消息内容。
所以在消费者拉取一条数据的时候,实际上是先查consume queue得到offset信息,然后再取commitLog拉取日志。
下图是逻辑队列存放一个信息的数据结构。
RocketMQ做了哪些性能提升措施?
下面列出比较普遍的优化点。
- 顺序写盘(CommitLog):提高写入效率,这个上面有介绍了,mysql binlog也是顺序写盘。
- 零拷贝:基于mmap+write模式,借助了底层DMA接口。
- 增加内存缓存PageCache(LRU):读取的时候优先查看PageCache是否命中,如果命中就直接返回,不用和io打交道,数据的写入也是优先写入内存缓存层。
- 当然还有很多系统层面的优化,如磁盘I/O调优。
实践经验
生产端:消息发送录入到日志上去,如有需要可以记录失败的记录到db上,方便排查问题,以及重试发送。
消费端:tcp机制,mq保证不会丢失消息的特性,生产端重复发送等因素都可能导致消费端重复消费,如有必要需要做服务幂等设计(增加ID插入表,比如把消息body内容做md5作为唯一ID)。
tip:tcp为了保证报文传输的可靠,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。
RocketMQ启动实践
说了这么多,我们看看怎么把RocketMQ本地run起来。
1.最基本的准备:idea开发工具,mvn环境,java环境等准备好。
2.到官网下载指定版本的bin文件,https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.7.0/rocketmq-all-4.7.0-bin-release.zip ,到这一步其实解压文件就可以执行脚本启动了,但是我们来通过idea来启动进行调试,继续往后走。
## Notice
### os.sh should be executed only once with root permission.
### os.sh parameter settings are for reference purpose only. You can tune them according to your target host configurations.
### Start broker
* Unix platform
`nohup sh mqbroker &`
### Shutdown broker
sh mqshutdown broker
### Start Nameserver
* Unix platform
`nohup sh mqnamesrv &`
### Shutdown Nameserver
sh mqshutdown namesrv
### Update or create Topic
sh mqadmin updateTopic -b 127.0.0.1:10911 -t TopicA
### Update or create subscription group
sh mqadmin updateSubGroup -b 127.0.0.1:10911 -g SubGroupA
启动成功有这样的日志。
3.配置RocketMQ环境:如果不配置直接执行脚本和后面idea启动的都时候会报错。Please set the ROCKETMQ_HOME variable in your environment to match the location of the RocketMQ installation
系统环境配置
sudo vi ~/.bash_profile
增加以下内容
export ROCKETMQ_HOME=/Users/xxxxx/rocketmq-all-4.7.0-bin-release
export PATH=${PATH}:${ROCKETMQ_HOME}/bin
source ~/.bash_profile
idea里面配置
4.从git上clone代码到本地:执行 git clone https://github.com/apache/rocketmq.git ,可能有点慢。
5.启动NameServer:搜索找到NamesrvStartup类。
6.启动Broker:搜索找到BrokerStartup类。
7.启动Consumer:启动代码给的压测case或者写一个消费类并且启动。
8.启动Producer:启动代码给的压测case或者写一个生产类并且启动。
参考文章:
https://helpcdn.aliyun.com/knowledge_detail/87277.html
https://baike.baidu.com/item/TCP/33012?fr=aladdin
由于个人能力有限,如有错误,还欢迎各位读者在CSDN聊天窗口多多批评指正,感激不尽。