Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
月凉、
JavaGuide
提交
628f9e2a
J
JavaGuide
项目概览
月凉、
/
JavaGuide
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
JavaGuide
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
628f9e2a
编写于
9月 16, 2021
作者:
G
Guide哥
提交者:
GitHub
9月 16, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1403 from anaer/patch-42
Update RocketMQ.md
上级
225e9986
90dd5e88
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
7 addition
and
7 deletion
+7
-7
docs/system-design/distributed-system/message-queue/RocketMQ.md
...ystem-design/distributed-system/message-queue/RocketMQ.md
+7
-7
未找到文件。
docs/system-design/distributed-system/message-queue/RocketMQ.md
浏览文件 @
628f9e2a
...
...
@@ -4,7 +4,7 @@
## 消息队列扫盲
消息队列顾名思义就是存放消息的队列,队列我就不解释了,别告诉我你连队列都不知道
似
啥吧?
消息队列顾名思义就是存放消息的队列,队列我就不解释了,别告诉我你连队列都不知道
是
啥吧?
所以问题并不是消息队列是什么,而是
**消息队列为什么会出现?消息队列能用来干什么?用它来干这些事会带来什么好处?消息队列会带来副作用吗?**
...
...
@@ -26,7 +26,7 @@
我们省略中间的网络通信时间消耗,假如购票系统处理需要 150ms ,短信系统处理需要 200ms ,那么整个处理流程的时间消耗就是 150ms + 200ms = 350ms。
当然,乍看没什么问题。可是仔细一想你就感觉有点问题,我用户购票在购票系统的时候其实就已经完成了购买,而我现在通过同步调用非要让整个请求拉长时间,而短
息
系统这玩意又不是很有必要,它仅仅是一个辅助功能增强用户体验感而已。我现在整个调用流程就有点
**头重脚轻**
的感觉了,购票是一个不太耗时的流程,而我现在因为同步调用,非要等待发送短信这个比较耗时的操作才返回结果。那我如果再加一个发送邮件呢?
当然,乍看没什么问题。可是仔细一想你就感觉有点问题,我用户购票在购票系统的时候其实就已经完成了购买,而我现在通过同步调用非要让整个请求拉长时间,而短
信
系统这玩意又不是很有必要,它仅仅是一个辅助功能增强用户体验感而已。我现在整个调用流程就有点
**头重脚轻**
的感觉了,购票是一个不太耗时的流程,而我现在因为同步调用,非要等待发送短信这个比较耗时的操作才返回结果。那我如果再加一个发送邮件呢?
![](
https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/16ef380429cf373e.jpg
)
...
...
@@ -44,7 +44,7 @@
![](
https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/006APoFYly1fvd9cwjlfrj30as0b03ym.jpg
)
那后来,我们工作赚钱了有钱去饭店吃饭了,我们告诉服务员来一碗牛肉面加个荷包蛋
**(传达一个消息)**
,然后我们就可以在饭桌上安心的玩手机了
**(干自己其他事情)**
,等到我们的牛肉面上了我们就可以吃了。这其中我们也就传达了一个消息,然后我们又转过头干其他事情了。这其中虽然做面的时间没有变短,但是我们只需要传达一个消息就可以
看
其他事情了,这是一个
**异步**
的概念。
那后来,我们工作赚钱了有钱去饭店吃饭了,我们告诉服务员来一碗牛肉面加个荷包蛋
**(传达一个消息)**
,然后我们就可以在饭桌上安心的玩手机了
**(干自己其他事情)**
,等到我们的牛肉面上了我们就可以吃了。这其中我们也就传达了一个消息,然后我们又转过头干其他事情了。这其中虽然做面的时间没有变短,但是我们只需要传达一个消息就可以
干
其他事情了,这是一个
**异步**
的概念。
所以,为了解决这一个问题,聪明的程序员在中间也加了个类似于服务员的中间件——消息队列。这个时候我们就可以把模型给改造了。
...
...
@@ -174,7 +174,7 @@
### RocketMQ中的消息模型
`Rocke
r
MQ`
中的消息模型就是按照
**主题模型**
所实现的。你可能会好奇这个
**主题**
到底是怎么实现的呢?你上面也没有讲到呀!
`Rocke
t
MQ`
中的消息模型就是按照
**主题模型**
所实现的。你可能会好奇这个
**主题**
到底是怎么实现的呢?你上面也没有讲到呀!
其实对于主题模型的实现来说每个消息中间件的底层设计都是不一样的,就比如
`Kafka`
中的
**分区**
,
`RocketMQ`
中的
**队列**
,
`RabbitMQ`
中的
`Exchange`
。我们可以理解为
**主题模型/发布订阅模型**
就是一个标准,那些中间件只不过照着这个标准去实现而已。
...
...
@@ -190,7 +190,7 @@
你可以看到图中生产者组中的生产者会向主题发送消息,而
**主题中存在多个队列**
,生产者每次生产消息之后是指定主题中的某个队列发送消息的。
每个主题中都有多个队列(分布在不同的
`Broker`
中,如果是集群的话,
`Broker`
又分布在不同的服务器中),集群消费模式下,一个消费者集群多台机器共同消费一个
`topic`
的多个队列,
**一个队列只会被一个消费者消费**
。如果某个消费者挂掉,分组内其它消费者会接替挂掉的消费者继续消费。就像上图中
`Consumer1`
和
`Consumer2`
分别对应着两个队列,而
`Consuer3`
是没有队列对应的,所以一般来讲要控制
**消费者组中的消费者个数和主题中队列个数相同**
。
每个主题中都有多个队列(分布在不同的
`Broker`
中,如果是集群的话,
`Broker`
又分布在不同的服务器中),集群消费模式下,一个消费者集群多台机器共同消费一个
`topic`
的多个队列,
**一个队列只会被一个消费者消费**
。如果某个消费者挂掉,分组内其它消费者会接替挂掉的消费者继续消费。就像上图中
`Consumer1`
和
`Consumer2`
分别对应着两个队列,而
`Consu
m
er3`
是没有队列对应的,所以一般来讲要控制
**消费者组中的消费者个数和主题中队列个数相同**
。
当然也可以消费者个数小于队列个数,只不过不太建议。如下图。
...
...
@@ -393,7 +393,7 @@ emmm,就两个字—— **幂等** 。在编程中一个*幂等* 操作的特
而在
`RocketMQ`
中采用了
`Dledger`
解决这个问题。他要求在写入消息的时候,要求
**至少消息复制到半数以上的节点之后**
,才给客⼾端返回写⼊成功,并且它是⽀持通过选举来动态切换主节点的。这里我就不展开说明了,读者可以自己去了解。
> 也不是说 `Dledger` 是个完美的方案,至少在 `Dledger` 选举过程中是无法提供服务的,而且他必须要使用三个节点或以上,如果多数节点同时挂掉他也是无法保证可用性的,而且要求消息复制
板书
以上节点的效率和直接异步复制还是有一定的差距的。
> 也不是说 `Dledger` 是个完美的方案,至少在 `Dledger` 选举过程中是无法提供服务的,而且他必须要使用三个节点或以上,如果多数节点同时挂掉他也是无法保证可用性的,而且要求消息复制
半数
以上节点的效率和直接异步复制还是有一定的差距的。
### 存储机制
...
...
@@ -425,7 +425,7 @@ emmm,是不是有一点复杂🤣,看英文图片和英文文档的时候就
首先,在最上面的那一块就是我刚刚讲的你现在可以直接
**把 `ConsumerQueue` 理解为 `Queue`**
。
在图中最左边说明了
<font
color =
red
>
红色方块
</font>
代表被写入的消息,虚线方块代表等待被写入的。左边的生产者发送消息会指定
`Topic`
、
`QueueId`
和具体消息内容,而在
`Broker`
中管你是哪门子消息,他直接
**全部顺序存储到了 CommitLog
**
。而根据生产者指定的
`Topic`
和
`QueueId`
将这条消息本身在
`CommitLog`
的偏移(offset),消息本身大小,和tag的hash值存入对应的
`ConsumeQueue`
索引文件中。而在每个队列中都保存了
`ConsumeOffset`
即每个消费者组的消费位置(我在架构那里提到了,忘了的同学可以回去看一下),而消费者拉取消息进行消费的时候只需要根据
`ConsumeOffset`
获取下一个未被消费的消息就行了。
在图中最左边说明了
<font
color =
red
>
红色方块
</font>
代表被写入的消息,虚线方块代表等待被写入的。左边的生产者发送消息会指定
`Topic`
、
`QueueId`
和具体消息内容,而在
`Broker`
中管你是哪门子消息,他直接
**全部顺序存储到了 CommitLog**
。而根据生产者指定的
`Topic`
和
`QueueId`
将这条消息本身在
`CommitLog`
的偏移(offset),消息本身大小,和tag的hash值存入对应的
`ConsumeQueue`
索引文件中。而在每个队列中都保存了
`ConsumeOffset`
即每个消费者组的消费位置(我在架构那里提到了,忘了的同学可以回去看一下),而消费者拉取消息进行消费的时候只需要根据
`ConsumeOffset`
获取下一个未被消费的消息就行了。
上述就是我对于整个消息存储架构的大概理解(这里不涉及到一些细节讨论,比如稀疏索引等等问题),希望对你有帮助。
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录