RocketMQ学习

RocketMQ(ons)特性

0拷贝 顺序写盘 随机读   延迟消息 事务消息 顺序消息 (rabbit没有这个)

基于netty nio框架

NameServer代替Zookeeper,寻址方式,更轻量级。

集群架构无单点,扩展性强。

消息重试机制,消息查询(rabbit不支持重试)

社区活跃、成熟度好

 模型

Producer 

Consumer

Broker

 

Netty分析

  • RemotingService
  • RemotingClient
    • 更新服务列表
    • 同步发送
    • 异步发送
    • 注册服务
      • 检查事务状态
    • 回调函数,生产者发异步消息的时候
  • RemotingServer
    • 注册admin接口
    • getProcessorPair
    • 同步发送
    • 异步发送
    • 这一块是netty编程模型 

  • netty底层源码解析
    • + 消息长度
    • + 序列化类型&&头部长度
    • + 消息头数据
    • + 消息主体数据。

racketMq: fastJson传输

 

消息投递 消息返回状态

  • send_ok 发送成功
  • flush_disk_timeout 有可能刷盘失败了
  • flush_slave_timeout 从节点同步失败
  • slave_not_available 从节点不可用

后三种要可靠性重投递。

延迟消息

在message上设置一个delayTimeLevel。发到broker后,会延迟。

 这个时间不能改,就固定选这些。

  • lv1 1s
  • lv2 5s
  • lv3 10s
  • 以此类推

 

怎么把消息发送到指定队列里

一个message默认有四个Mseeage Queue

MessageQueueSelector 负载均衡策略 轮询去发消息

cousumer 也是轮询消费

producer.send(Msg, selector, Obj);   selector就是指定发送的对象

 

Broker存储结构

consumer Queue

  记录了,消息偏移量信息  ;对commit log的关系类似于索引对数据库的关系;queue是内存中的,性能好。

consumer_Queue

当我们需要消费某个topic的消息时,通过对Commit Log整体遍历寻找消息的方式无疑非常的低效。所以本章将引出2个很重要的概念:消费队列IndexFile

与commitLog只有一个文件不同,consumeQueue是每个topic的每个消费队列都会生产多个文件

 

 

 

 

commit Log

  所有信息,包括偏移信息 

消息存储(CommitLog) 

commit log虽说是单文件结构,但是并不是所有的message都存储在同一个物理文件中,Rocket MQ设定了单commit log的文件大小为固定1G,而命名则与kafka相似:总长度20位,标记当前文件的物理偏移量,高位用0补齐,如下:

  • 00000000000000000000 第一个文件,物理偏移量为0
  • 00000000001073741824 第二个文件,物理偏移量为1G
  • 00000000002147483648 第三个文件,物理偏移量为2G
  • 00000000003221225472 第四个文件,物理偏移量为3G
  • ......

问:为什么要每个文件设定1G大小呢?

答:虽然FileChannel在映射文件时,size的入参是long值,但FileChannel内部会判断size是否超过了`Integer.MAX_VALUE`(2147483647),如果超了,会扔出`IllegalArgumentException`异常,而2147483647正好小于2G,所以文件映射无法一次性映射一个大于等于2G的文件,再加上减少理解投入及文件过期等因素,故设定commit log文件均为1G

问:因为消息都是变长字段,假如第一个文件还没写满1G,但新的消息又写不进去时,怎么处理呢?

答:其实这种情况一定会存在,解决策略是在每个文件的结尾会写入“尾部空余大小(4byte)”,以及“结束标记魔法值(4byte)”,此魔法值为固定值-875286124

写盘方式 随机写 顺序读

消费端 0拷贝 

 

同步刷盘 异步刷盘

内存+磁盘存储两种刷盘方式

异步刷盘

同步刷盘

 

事务消息

不用事务的话,阻塞,增加处理时间,降低了RT。

架构场景

例子:支付A和支付B怎么可靠性解耦

  1. 消息发到MQ集群,同时提交事务A账户-100。
  2. 提交本地事务,发一个确认消息。
  3. 3这个时候才可见,之前不可见。

问题是:

2确认消息有可能发送失败,那一直都不可见。用mysql的存储,例如:0是不可见,1可见

解决:

MQ集群主动查询生产端,check是否成功。发ACK。

不断重试。

 代码例子

(大致)

 

 

 顺序消息

消费顺序和生成的顺序是相同的。例如场景:生成订单、付款、发货。

分为:

  • 全局顺序
    • 生成消费都是1个,这样才行。
  • 局部顺序
    • 保证每一组消息顺序执行
    • 生产和消费都要做限制才行
    • 要求:
      • 投递到同一个消息下,同一个队列中。
      • 消费端就是单线程取。读栈的模式。

 消费端

 

 

 

 

 

 

相关问题:

1.为什么使用mq,具体场景是什么?

  削峰填谷;扣减预算,积分,同步数据,记录日志,巡检优化,bcp检查,数据兜底。

2.使用什么mq,基于什么选型

  同事推荐;大qps单机最大写50Wtps;支持分布式高并发业务;有事务消息和顺序消息。

3.异步发送,怎么保证消息可靠性

  防止生产者丢失:异步有回调和异步无回调;本地消息表,更改状态,人工介入。

  防止MQ本身丢失:同步刷盘和异步刷盘,根据业务做取舍,异步的不可靠,但是效率高。

  防止消费者丢失:消费成功返回resume,否则一直执行,直到进入死信队列,人工处理。

4.消费失败重试,导致消息积压,怎么处理?

  修复时,同时建一个consumer去消费当前消息,记录消息内容。

  修复问题代码或服务。

  重试消息。

5.消息积压达到磁盘上限,消息丢失怎么办?

  本地消息表,筛选出未成功的数据。

6.rocketMq

  nameServer 注册中心

  producer 生产者集群

  consumer 消费者

7.为什么注册中心不用zookeeper

  1. zk满足cp,不能保证可用性。
  2. nameServer轻量级,水平扩展性好,
  3. 持久化机制zk太重
  4. 若依赖注册中心,从nameServer获取broker地址后,在生产者本地缓存。

8.brocker是怎么保存数据

9.master和slave是怎么同步的

raft协议 broker收到消息 置为uncommited,随后置为slave,置为commit。

10.Rocket为什么速度快

顺序存储,pagecache,异步刷盘。

 

posted @ 2023-07-31 17:02  CodingOneTheWay  阅读(23)  评论(0编辑  收藏  举报
回到顶部