消息队列
发展历程
常见的消息队列
Kafka
Kafka可以参考这个链接:blog.csdn.net/aaa_a_b_c/a…
使用场景
可以通过metrics数据监控查询等耗时问题
日志信息、Metric数据、用户行为等在kafka中都会被放到消息队列中
使用kafka
topic指的是业务场景,所有有关的业务场景都存储在topic中
基本概念
partition是topic的一个分区的概念 不同分区的消息可以并发处理
partition会有多个不同的负载 分布在不同的机器上
leader负责对外写入或者读取
follower负责从leader拉取信息 尽量与leader保持一致,如果和leader差距太大的话就会被踢出ISR,如果leader宕机之后可以从ISR中选择follower先顶替leader的工作
topic和broker没有明确的对应关系。topic只是一个逻辑上的概念,对消息进行分类。topic在物理上分成多个partition,单独以 leader parition论,partition均匀的分布在broker上,这样做的好处是1、可以负载均衡,2、可以并行发送消息。
数据复制
topic1也就是leader在不同的分区上 他在每个分区中相当于controller的角色
但是这种方式存在问题
当我们重启其中一个broker的leader的时候,会重新选择一个新的leader 数据的使用还在进行 可能会导致broker之间的数据存在差异(黑色的虚线箭头表示数据的复制) ,所以需要进行数据的同步与追赶,最后需要进行一个leader的回切(防止大部分的leader都跑到其他节点,从而出现负载均衡的问题)
除了重启之外,也可以通过其他方式进行
替换和重启类似
只要有节点的变更都会消耗时间
kafka架构
主要就是生产者、集群和消费者群
Producer
Broker
broker 如何存储数据?
以日志的形式存储
通过磁盘结构来读写
- 磁头移动到指定的磁道上(移动磁头的时间比较长)
- 磁盘转动,找到对应的扇区
- 在扇区上进行读写
通过顺序写的机制来写入,以减少寻道的时间
如何读取消息,首先会发送一个fetchrequest请求给broker
采用的是稀疏索引的方式
时间戳索引相对于偏移量索引多加了一个时间戳到offset的查找的步骤 也就是第一个块
找到数据之后 在发送给consumer之前需要做一些拷贝,因为数据存储在磁盘中 需要先将数据拷贝到内核空间中才能给到用户空间 最后通过网卡内存(NIC)将数据发送给消费者(这种方式开销比较大)
传统的数据拷贝开销较大 kafka使用了零拷贝的方式,直接在内核空间中进行数据的拷贝而不需要通过应用空间
同理 写入也使用了相同的拷贝方式,即零拷贝(写入的时候直接写入内核空间)
Consumer
手动分配
- 如果其中一个consumer挂了,比如consumer3挂了,分区7和分区8的数据流就会断掉(不能自动容灾)
- 重新加一个consumer也得重新分配
- 优点是:比较快
自动分配
分配过程
有consumer进来之后首先会随机选择一个broker(负载比较低的)
之后broker会告诉consumer他对应的协调者是具体的哪个broker
然后consumer会发起第二轮请求找到对应的协调者 说consumer想要加入到这个cluster中
broker会从consumer中选取一台当做leader,用来计算整个分布的策略
这是因为对于某些特定的业务来说,有自己的业务特性 希望某个分片分配到某个特定的consumer上
第三个请求用来同步整个集群的方案数据等
连接成功之后每个consumer会在一定间隔内给cluster发送心跳
负载不均衡问题
可以将其中的partition迁到另一个broker中 但是迁出的时候会有数据复制的问题 (需要进行权衡)
存在问题
BMQ
优点:兼容kafka协议,存算分离,云原生消息队列
整体架构
相比于kafka来说增加了代理模块和分布式存储系统
HDFS
写文件流程
数据不会都分配在同一个节点 上图中共数据选择是哪个节点进行写入,然后随机的在dataNode上进行分配(比如P1S1 分别分配在,1 2 3 DataNode)
broker状态机
不会在同一个broker中有相同的分片,分片会在规定的机制下进行流转
recover:争夺使用权,抢锁,即一个文件只能有一个进程来写入;检查broker是否处于宕机等问题状态,如果是的话直接进行数据写入会造成问题,因此需要recover进行broker的恢复
fileover:如果append数据的时候出现异常 用来保证数据不会被中断
write thread 异步处理
如果写入到buffer中就算写入成功的话:会有很高的吞吐,但是如果只写入到buffer中但是还没写入到磁盘中此时磁盘宕掉了,那么会造成写入数据的丢失
checkpoint:相当于一个标识,表示已经写入磁盘并且建立了索引,和上一张的checkpoint相同
如果datanode挂了 failover机制会找一个其他的datanode继续进行写入操作 而不是等待原来的那个修复
proxy读取数据
wait:如果没有wait机制的话 topic如果没有读取到数据会一直轮训,io压力较大;wait中设置了两种返回方式:1. 数据大小到达一定量的时候返回 2. 超过设置时间之后还没到读取一定量的数据也会进行返回
多机房部署
proxy一个就可以工作了
broker需要全部一起进行工作
高级特性
可应对复杂场景
两种BOE测试各有优缺点
将主干和泳道的topic分开
Databus
解决
agent 所有消息都会发送到agent,然后再由agent发送给BMQ
server 保存配置
mirror
通过mirror可以异步写入,如果写入都是CN可以直接写,同时也不会影响其他区域的写入,然后通过mirror将写入的内容分发到其他区
index
parquet
RocketMQ
VS.Kafka
基本概念
架构
Nameserver(充当路由的角色): 告诉生产者消费者在哪个broker上可以更加准确的进行消费或者生产
整个机器是一个master 而另一个机器是slave
消息存储
所有消息都会发送到broker上,每一个broker只有一个commitLog,会承接所有生产者数据,然后根据不同的分区dispatch出去,但是中间T1:Q0中存储的不是真实数据 而是真实数据在commitLog中的地址,相当于是个索引(而且是个立即索引)
每个Producer group只有一个commitLog来承接所有的数据 然后根据不同的分区来dispatch
高级特性
把消息写入到队列中,然后再异步的处理
需要用到事务保证库存记录-1和将消息放入到消息队列共同进退
提前将消息发送到队列中并且给消息设置好可以消费的时间
丢掉消息还是重新发送?