利用工具分析Leader节点
进行dump
1、按照文档dump https://developer.hashicorp.com/consul/commands/debug
命令: consul debug -interval=5s -duration=30s -capture agent
2、使用可视化工具查看
需要安装golang,安装Graphviz,这里不多做赘述。
命令:go tool pprof profile.prof
输入:web


1、按照文档dump https://developer.hashicorp.com/consul/commands/debug
命令: consul debug -interval=5s -duration=30s -capture agent
2、使用可视化工具查看
需要安装golang,安装Graphviz,这里不多做赘述。
命令:go tool pprof profile.prof
输入:web


之前我们进行RocketMQ的搭建,其中有一个参数是用来配置刷盘方式的。存在“同步”和“异步”两种方式。
1 | flushDiskType=ASYNC_FLUSH|SYNC_FLUSH |
和刷新磁盘逻辑相关的代码可以从这里开始看DefaultFlushManager
1 | class DefaultFlushManager implements FlushManager { |
从构造函数可以看到,要理解刷盘的行为,需要搞懂GroupCommitService同步刷盘,FlushRealTimeService 异步刷盘和CommitRealTimeService这三个类的名称取的不是很便于记忆和理解。
为了理解刷盘操作,我们去看更上一层的逻辑。在Broker接收到客户端的消息写入请求,并完成一系列的解析、校验放入内存等工作后。后续就需要将消息持久化到磁盘。
1 | public CompletableFuture<PutMessageStatus> handleDiskFlush(AppendMessageResult result, MessageExt messageExt) { |
GroupCommitService和FlushRealTimeService的主要区别在于调用flush传入的刷新数据页数(RocketMQ内部逻辑概念,和计算机系统的页无关)。GroupCommitService每次都做刷新都传入0,FlushRealTimeService则按照规则进行计算出页数。我这边按照原逻辑改写的容易理解的伪代码:
1 | int flushPhysicQueueLeastPages = 4; |
这段代码避免了短时间内进行多次全量刷盘,从而提高了刷盘效率和性能呢。正因为异步刷盘不是每次都是全量刷盘,从这个角度来看才会被称为异步刷盘,其实本质上都是异步进行刷盘的。
我们在上述刷盘代码中看到了此配置项。该配置项是为了提高IO性能,但是在Broker JVM进程异常退出的时候增加丢消息的风险。感兴趣的同学可以看这篇文章
Broker的功能点很多,安装程序启动的顺序去看源码,发现代码量比之前的组件要大很多。阅读过程中发现Broker会去持久化一些配置,并且会将消息数据存储在磁盘上。
整理和检索了网上的一些资料,列出了这些文件和相应的作用,如下。
最近闲来无事,想体验一下NAS的玩法。那么说干就干。
发扬垃圾佬的精神,追求极致性价比。性能、功耗、价格不可能三角,尽量把钱花在刀刃上。考虑静音,所以必须要no fans。
网上查了一些资料,大概看了如下几款cpu。
| cpu | 制程 | 主频 | TDP | 价格 |
|---|---|---|---|---|
| J3160 | 14nm | 4核4线程 1.6GHz | 6w | 板u 100 rmb左右 |
| J1900 | 22nm | 4核4线程 2.42GHz | 10w | 整个小主机或者软路由某鱼200rmb |
| N5095 | 10nm | 4核4线程 2GHz | 15w | 板U 538rmb |
从这3个cpu看,J3160不论功耗还是价格,对我来说是最为合适的。而且ddr3的内存也是价格实惠。功耗比较喜人才6w。算一下一年电费多少,假设整机功耗10w:
相当喜人。。。
| 配件 | 来源 | 价格 |
|---|---|---|
| 铭瑄N3160 | 闲鱼 | 106 |
| 动力之星dc转atx电源转换卡 | 拼多多 | 43 |
| 悠品12V5Adc电源 | 京东一手 | 38 |
| ddr3 1600内存条8GB台式机内存 | 闲鱼 | 43 |
| 开机按钮 | 拼多多 | 5 |
| 硬盘120GB SSD | 闲鱼 | 43 |
| 8GB u盘 安装黑群晖 | 京东 | 14 |
| SATA线*2 | 京东 | 9 |
| 总计 | 301 |
该组件的核心就是一个Raft协议的实现。这个Raft协议的实现用的也不是淘宝系的JRaft,而是第三方的产品DLedger。对于生产要求比较严格的大厂,这个倒是比较意外。
用这个组件一般就是用来实现选主,或者当一个存储数据库来使用。前几篇有说过RocketMQ使用ControllerManager组件来实现的灾备切换,那么我们来看一下究竟是如何实现的。
| 名称 | 描述 | Raft操作类型 |
|---|---|---|
| CONTROLLER_ALTER_SYNC_STATE_SET | 往Raft日志同步syncStateSet | 写 |
| CONTROLLER_ELECT_MASTER | 进行leader选举,将最终选出的Leader同步到Raft日志。让人震惊的是选主没有使用到Raft,而是自己实现的策略。 | 写 |
| CONTROLLER_GET_REPLICA_INFO | 按照brokerName获取所有broker信息 | 读 |
| CONTROLLER_GET_METADATA_INFO | 获取当前Raft集群所有Peer信息 | 读 |
| BROKER_HEARTBEAT | Broker进行心跳 | 无 |
| CONTROLLER_GET_SYNC_STATE_DATA | 获取syncStateSet数据 | 读 |
| UPDATE_CONTROLLER_CONFIG | 更新ControllerManager配置 | 无 |
| GET_CONTROLLER_CONFIG | 读取ControllerManager配置 | 无 |
| CLEAN_BROKER_DATA | 清理Broker数据 | 写 |
| CONTROLLER_GET_NEXT_BROKER_ID | 获取下一个BrokerId | 读 |
| CONTROLLER_APPLY_BROKER_ID | 写入BrokerId | 写 |
| CONTROLLER_REGISTER_BROKER | 使用唯一的BrokerId注册Broker | 写 |
我选择的源码版本是5.1.4 源码地址来进行学习,如下是来自官方的架构图

按照5.0弹性无状态代理模式的架构图,我们可以将RocketMQ 分为如下主要模块:
Console/MqAdmin
Proxy
Broker (local模式下与Proxy部署在同一个进程,cluster模式下和Proxy分为两个进程部署)
NameServer
Controller(ControllerManager) 可以和NameServer部署在同一个进程
该组件使得RocketMQ具有,主备自动切换的能力。
6.各种语言的Client
各个组件的功能作用,后面再一个个分析和解释。但我想有些中间件和架构爱好者看这个图,就能大概知道各个组件有啥用途。
最近上班比较清闲,之前一直在微信读书上读了不少闲书。颇有游手好闲,不务正业的样子。最近内心思索半天,觉得这样下去自己的职业生涯可能走不远。又由于最近公司在考虑消息队列的选型,所以想着花点时间去深入了解一下消息队列的机制。一方面是对RocketMQ比较感兴趣;另一方面也是希望对所学的技术做一个记录,将来出去面试,作为展示自我技术学习成果的窗口。
为什么选择RocketMQ?
Java 事务消息 社区活跃 支撑阿里的业务
我准备带着一些问题去进行阅读,相比于一头扎进代码海洋,这样更有针对性,并且收获可能更大。这样的一个大型开源产品,不去看一些细枝末节的细节,可能更有效率,也更节约时间。
带着哪些问题去看?
1、NameServer服务注册机制?
2、消息底层文件存储机制?
3、定时消息实现机制?
4、顺序消息实现机制?
5、事务型消息实现机制?
6、高可用、故障转移机制?