Análisis y resumen del esquema de retraso de RocketMQ

Equipo técnico de Zhengcaiyun.png

Saber y hacer.png

1. Antecedentes y motivación

1.1 Concepto

  • Mensaje de sincronización: el Productor envía el mensaje al servidor de la versión RocketMQ de la cola de mensajes, pero no espera entregar el mensaje de inmediato, sino que retrasa la entrega al Consumidor para que lo consuma en un momento determinado después del punto de tiempo actual. mensaje de temporización.
  • Mensaje retrasado: El Productor envía el mensaje al servidor de la versión RocketMQ de la cola de mensajes, pero no espera entregar el mensaje inmediatamente, sino que lo retrasa por un cierto período de tiempo antes de entregarlo al Consumidor para su consumo. es un mensaje retrasado.

Hay algunas diferencias en la configuración del código entre los mensajes cronometrados y los mensajes retrasados, pero el efecto final es el mismo: el mensaje no se entregará inmediatamente después de enviarse al servidor RocketMQ de la cola de mensajes, sino que se retrasará por un tiempo fijo. según los atributos del mensaje entregado a los consumidores.

1.2 ¿Qué problema pretende resolver esta propuesta?

Actualmente, en la función de RocketMQ (versión comunitaria), ya se admiten los mensajes retrasados. Pero solo se admite una granularidad fija del nivel de retraso (18 niveles) para esta función, como por ejemplo:

1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h。
复制代码

Aunque estas granularidades se pueden configurar, aún no pueden hacer frente a una amplia gama de escenarios comerciales.

比如定义了 1s 、5s 的 Level,那么用户只能发送 1s 或 5s 的延时消息,不能发送 3s 延迟的消息。
复制代码

En comparación con la versión RocketMQ (Alibaba Cloud), ya admite mensajes con cualquier retraso dentro de los 40 días.

( Nota: en este artículo, discutiremos cómo transformar el esquema de mensajes de retraso arbitrarios en RocketMQ (versión comunitaria). )

2. Metas

Agregue la función de mensajes de retraso arbitrarios en RocketMQ (versión comunitaria):

  • La precisión es compatible con el segundo nivel.

  • Se admite un retraso de hasta 30 días

3. Dificultades

Entonces, ¿cuál es la dificultad de retrasar arbitrariamente los mensajes?

  • clasificar

Para los mensajes retrasados ​​recibidos por el servidor, se debe ordenar el tiempo de entrega. En MQ, para garantizar la confiabilidad, los mensajes deben colocarse en el disco y los requisitos de rendimiento y demora determinan que es completamente inaceptable clasificar los mensajes en el lado del servidor.

  • almacenamiento de mensajes

对于延时消息来说,需要存储最近30天的消息。而 RocketMQ 是基于 WAL,对于高流量的场景下,存储 30 天的消息需要多少服务器。

四.设计思路 (Design)

4.1 原延时方案 (Original scheme)

先来看一下原延时方案的设计:

对于 normal msg 来说:

  • 消息会被顺序写入 commitlog;

  • 在异步 reput 中,通过 DispatchService 生成对应的 consumer queue 索引;

  • 消费者即可以消费对应的消息。

对于 delay msg 来说:

  • 消息在被写入 commitlog 前,会将 topic 设置为 SCHEDULE_TOPIC,并将 real topic 保存在 properties 中,并且将 queueId 设置为 delay level 的值;

  • 在异步 reput中,通过 DispatchService 会生成 SCHEDULE_TOPIC 的 consumer queue,共18个;

  • 在 ScheduleMessageService 中给每个 level 设置定时器,从 ScheduledConsumeQueue 中读取信息。如果 ScheduledConsumeQueue 中的元素已经到时,那么从 CommitLog 中读取消息内容,恢复消息内容写入 CommitLog,再按 normal msg 消费。

方案分析:

  • 优点1:将排序转化为分类

  • 优点2:Level数固定即线程数量固定,开销不大

  • 缺点1:固定Level,不够灵活

  • 缺点2:若延时很长,会导致CommitLog的量很大

4.2 新延时方案 (New scheme)

4.2.1 如何解决排序

我们可以用原方案类似的方式,用分类操作解决排序。

可以使用 TimeWheel:《Hashed and Hierarchical Timing Wheels: Data Structures for the Efficient Implementation of a Timer Facility》

我们只需要将即将发送的消息加载到TimeWheel中,再按时间取出delay msg将其放入real topic中。

这里的“即将发送的消息”可以定义为 30 分钟(timeSliceLength)内的消息,TimeWheel中每一个格子为1秒,那么一个 TimeWheel 为 1800格。

这里我们可以估算一下TimeWheel的内存需求,按每个消息 500B,那么 200万 个消息则需要 1G 的内存。

我们可以根据延迟消息的量,来设置 timeSliceLength 的大小。以下我们将以 timeSliceLength=1800 展开讨论。

4.2.2 如何解决消息存储

将延时消息单独存储至 CommitLog(以下将此称为“DCommitLog”)

那么如何设计 DCommitLog?我们可以将时间段按 timeSliceLength 进行散列,将整个 timeSliceLength 时间内的 delay msg 放入同一个 DCommitLog 中:

# 公式
SliceTime = timestamp / timeSliceLength / 100

# 若delay msg的投递时间为 1641349066282,则带入公式得到
    1641349066282 / 1800 / 1000 = 911860
# 即该消息会被写入 911860 的 DCommitLog 中。
复制代码

4.2.3 延时方案

有了以上基本的概念,我们设计一下整个延时方案:

ScheduleMessageService 主要完成 DispatchMsg 和 TimeWheelTask。

  • DispatchMsg 对 SCHEDULE_TOPIC 按 delayOffset 进行内部消费,并根据 deliveryTime 将消息投递到 real topic、TimeWheel、DCommitLog。
  • TimeWheelTask 则按 currentTime 从 TimeWheel 取出消息投递到 real topic 并提前加载下一个时间片的消息、切换 TimeWheel。这里的 currentTime 是 TimeWheel 所用的,而非现实的时间戳。
  • delayOffsetcurrentTime 需要落盘到 delayOffset.json。

  1. 消息在被写入 commitlog 前,会将 topic 设置为 SCHEDULE_TOPIC,并将 real topic 保存在 properties 中,并且将 queueId 设置为1;
  2. consume with delayOffset:根据 delayOffset 消费 SCHEDULE_TOPIC,得到 delay msg;
  3. 根据 delay msg 计算 deliveryTime,若 deliveryTime < currentTime,即消息已经超时直接将消费放入 real topic,进入7,否则进入4;
  4. 若 deliverySliceTime == currentSliceTime,即消息在本时间片内,将其放入 TimeWheel 和 DCommiLog 中,进入7,否则进入5;
  5. 若 deliverySliceTime == currentSliceTime +1 && nextTimeWheel != null,即消息在下一时间片并且下一时间轮已经加载,则将消息放入 nextTimeWheel 和 DCommitLog,进入7,否则进入6;
  6. 消息在后面的时间片后,直接将其放入 DCommiLog 中;
  7. 根据 currentTime 从 TimeWheel 获取需要投递到 real topic 中的消息集合;
  8. 投递到 real topic;
  9. 若还没有开始加载下一个时间片的数据,未开始加载进入10,已开始则进入11;
  10. 若 currentTime 接近 nextTimeSlice,异步加载下一个时间片 DCommiLog 中的数据到下一个时间轮中,否则12;
  11. 若 currentTime 已经到 nextTimeSlice,则将时间轮切换至下一个时间轮;
  12. 更新 currentTime、delayOffset,每次 currentTime 最多增长1秒,且不能超过 system.currentTimeMillis(),进入2;

4.3 总结 (Summary)

以上流程,分为 DispatchMsg、TimeWheelTask,DispatchMsg 分发 delay msg 将其归类到 DCommitLog 中,TimeWheelTask 则取出 DCommitLog 放入 TimeWheel 中进行时间调度并将 msg 放入 real topic 中。

方案待优化

DCommitLog 会带来随机读写的问题,用 mmp 的同时也会影响 CommitLog 的 PageCache。

可以考虑 normal broker 和 delay broker 分离部署的方式来解决或者调整 DCommitLog 的文件大小优化。

另外因为 TimeWheel 存在在内存中,对于 JVM 的内存需求也会随之上升。

4.3.1 对应的MASTER-SLAVE、DLeger模式需要作何处理?

  • 在 MASTER-SLAVE 中,由于 SLAVE 没有写入权限 TimeWheelTask 则不需要启动,而 SLAVE 不会自动切换 Master,也就不需要生成 DCommitLog;只能重启 master;

  • 在 DLeger 模式中,SLAVE 同样没有写入权限,TimeWheelTask 不需要启动。但是 SLAVE会自动切换 Master,此时需要生成 DCommitLog 用于在容灾恢复后保证 delay msg 可以正常被消息。这里需要将 Matser的delayOffset.json 的数据同步到 Slave 上。

4.3.2 对重试策略的影响

由于重试依赖于原延时方案的固定粒度时间间隔,在使用本方案改造后需要对 sendMessageBack 做额外重试策略的处理。

4.3.3 方案注意事项

1、DCommitLog 会带来随机读写的问题,用 mmp 的同时也会影响 CommitLog 的 PageCache。可以考虑 normal broker 和 delay broker 分离部署的方式来解决或者调整 DCommitLog 的文件大小优化。

2、因为 TimeWheel 存在在内存中,对于 JVM 的内存需求也会随之上升。对于延迟消息使用较高的场景需要特别注意合理设置 JVM 大小。优化:TimeWheel 中的 msg 改为 msg 的 offset,可明显降低 JVM 的内存需求,1G=6250万 条消息

以上就是《RocketMQ延时方案分析与总结》, 希望能给你在工作中起到辅助作用,如有任何问题可以在评论区中提出你的想法和建议。

推荐阅读

Dapr 实战(一)

Dapr 实战(二)

政采云Flutter低成本屏幕适配方案探索

招贤纳士

El equipo técnico de Zhengcaiyun (Zero), un equipo lleno de pasión, creatividad y ejecución, la Base se encuentra en la pintoresca Hangzhou. El equipo cuenta actualmente con más de 300 socios de I+D, incluidos soldados "veteranos" de Ali, Huawei y NetEase, así como recién llegados de la Universidad de Zhejiang, la Universidad de Ciencia y Tecnología de China, la Universidad de Hangdian y otras escuelas. Además del desarrollo comercial diario, el equipo también lleva a cabo exploración técnica y práctica en los campos de la nube nativa, blockchain, inteligencia artificial, plataforma de código bajo, middleware, big data, sistema de materiales, plataforma de ingeniería, experiencia de rendimiento, visualización, etc. Y aterrizó una serie de productos de tecnología interna y continuó explorando nuevos límites de tecnología. Además, el equipo también se ha dedicado a la creación de comunidades. Actualmente, son colaboradores de muchas comunidades excelentes de código abierto, como google flutter, scikit-learn, Apache Dubbo, Apache Rocketmq, Apache Pulsar, CNCF Dapr, Apache DolphinScheduler, alibaba Seata , etc. Si quieres cambiar, te han tirado con cosas, y quieres empezar a tirar cosas; si quieres cambiar, te han dicho que necesitas más ideas, pero no puedes romper el juego; si quieres cambio, tienes la capacidad de lograr ese resultado, pero no te necesitas a ti; si quieres cambiar lo que quieres lograr, necesitas un equipo que lo apoye, pero no hay lugar para ti para liderar personas ; si quieres cambiar, tienes un buen entendimiento, pero siempre hay un desenfoque de esa capa de papel de la ventana... Si crees en el poder de la creencia, creo que la gente común puede lograr cosas extraordinarias, y creo que puedan encontrarse con un yo mejor. Si desea participar en el proceso de despegue a medida que despega el negocio y promover personalmente el crecimiento de un equipo técnico con un conocimiento profundo del negocio, un sistema técnico sólido, tecnología que crea valor e influencia indirecta, creo que deberíamos hablar. En cualquier momento, esperando que escribas algo, envíalo a [email protected]

Cuenta pública de WeChat

El artículo se publica simultáneamente, la cuenta pública del equipo técnico de Zhengcaiyun, bienvenido a prestar atención.

Equipo técnico de Zhengcaiyun.png

Supongo que te gusta

Origin juejin.im/post/7088841619515899934
Recomendado
Clasificación