RocketMQ 学习相关

RocketMQ vs. ActiveMQ vs. Kafka

Messaging Product Client SDK Protocol and Specification Ordered Message Scheduled Message Batched Message BroadCast Message Message Filter Server Triggered Redelivery Message Storage Message Retroactive Message Priority High Availability and Failover Message Track Configuration Management and Operation Tools
ActiveMQ Java, .NET, C++ etc. Push model, support OpenWire, STOMP, AMQP, MQTT, JMS Exclusive Consumer or Exclusive Queues can ensure ordering Supported Not Supported Supported Supported Not Supported Supports very fast persistence using JDBC along with a high performance journal,such as levelDB, kahaDB Supported Supported Supported, depending on storage,if using levelDB it requires a ZooKeeper server Not Supported The default configuration is low level, user need to optimize the configuration parameters Supported
Kafka Java, Scala etc. Pull model, support TCP Ensure ordering of messages within a partition Not Supported Supported, with async producer Not Supported Supported, you can use Kafka Streams to filter messages Not Supported High performance file storage Supported offset indicate Not Supported Supported, requires a ZooKeeper server Not Supported Kafka uses key-value pairs format for configuration. These values can be supplied either from a file or programmatically. Supported, use terminal command to expose core metrics
RocketMQ Java, C++, Go Pull model, support TCP, JMS, OpenMessaging Ensure strict ordering of messages,and can scale out gracefully Supported Supported, with sync mode to avoid message loss Supported Supported, property filter expressions based on SQL92 Supported High performance and low latency file storage Supported timestamp and offset two indicates Not Supported Supported, Master-Slave model, without another kit Supported Work out of box,user only need to pay attention to a few configurations Supported, rich web and terminal command to expose core metrics

启动过程

Start Name Server
nohup sh bin/mqnamesrv &
tail -f ~/logs/rocketmqlogs/namesrv.log

Start Broker
nohup sh bin/mqbroker -n localhost:9876 &
tail -f ~/logs/rocketmqlogs/broker.log

Send & Receive Messages
export NAMESRV_ADDR=localhost:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

Shutdown Servers
sh bin/mqshutdown broker
sh bin/mqshutdown namesrv

基本概念

消息模型(Message Model)
RocketMQ主要由 Producer、Broker、Consumer 三部分组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。Broker 在实际部署过程中对应一台服务器,每个 Broker 可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的 Broker。Message Queue 用于存储消息的物理地址,每个Topic中的消息地址存储于多个 Message Queue 中。ConsumerGroup 由多个Consumer 实例构成。
消息生产者(Producer)
RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。
消息消费者(Consumer)
主题(Topic)
代理服务器(Broker Server)
消息中转角色,负责存储消息、转发消息。代理服务器在RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等。
名字服务(Name Server)
名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,但相互独立,没有信息交换。
就是根据topic 查询对应的那些 broker存储消息,类似于 kafka 的 ZK;
拉取式消费(Pull Consumer)
推动式消费(Push Consumer)
生产者组(Producer Group)
消费者组(Consumer Group)
RocketMQ 支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)。
集群消费(Clustering)
集群消费模式下,相同Consumer Group的每个Consumer实例平均分摊消息
广播消费(Broadcasting)
广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息。
普通顺序消息(Normal Ordered Message)
普通顺序消费模式下,消费者通过同一个消息队列( Topic 分区,称作 Message Queue) 收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的。
严格顺序消息(Strictly Ordered Message)
严格顺序消息模式下,消费者收到的所有消息均是有顺序的。
消息(Message)
RocketMQ中每个消息拥有唯一的Message ID,且可以携带具有业务标识的Key。系统提供了通过Message ID和Key查询消息的功能。
标签(Tag)
总结下主要和kafka不一样的点:

  1. 消费推拉都支持
  2. 消费模式多样,同时支持集群消费和广播消费
  3. 消费顺序多样,比如普通顺序消息就是kafka的方式, 同时还支持严格顺序消息 类似于kafka只有一个分区
  4. 消息体默认具有唯一的Message ID,也可以自己指定具有业务标识的Key和kafka类似, 但是不同的是 RQ 提供了通过Message ID和Key查询消息的功能。
  5. tag 可以在一个topic内,对不同的消息打标签

特性(features)

https://github.com/apache/rocketmq/blob/master/docs/cn/features.md
消息顺序:比如 订单创建、订单付款、订单完成 三个消息对于同一个订单,必须保证严格按照顺序消费才有意义。
顺序消息分为全局顺序消息与分区顺序消息;

  • 全局顺序 对于指定的一个 Topic,所有消息按照严格的先入先出(FIFO)的顺序进行发布和消费。 适用场景:性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景。类比kafka 一个partition
  • 分区顺序 对于指定的一个 Topic,所有消息根据 sharding key 进行区块分区。 同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费。 Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念。 适用场景:性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。类比kafka按照shardkey 进行分区
    消息过滤:
    目前支持2种, 1 是根据消息的tag进行过滤, 或者自定义过滤规则,目前RQ 这些是在broker实现的, 好处是减少 consumer端的开销。缺点是实现比较复杂。
    消息可靠性:
  1. 机器挂了但是是马上可以恢复的,RQ 可以保证消息不丢失,或者丢失少量, 依赖刷盘是同步还是异步
  2. 若机器磁盘坏了, 单点故障无法恢复,这就依赖于分片的写策略了,若是异步写可以保证99%数据不丢失 , 若是同步双写可以保证100% 不丢失,但是开启同步双写会影响性能。
    回溯消费:
    就是业务逻辑出问题了, 需要重新消费, RQ 支持按照时间回溯,可以精确到毫秒级别。
    事务消息:
    该特性是其与其他消息存储的最大不同,包括 kafka 、rabbitmq ...
    RocketMQ事务消息(Transactional Message)是指应用本地事务和发送消息操作可以被定义到全局事务中,要么同时成功,要么同时失败。RocketMQ的事务消息提供类似 X/Open XA 的分布事务功能,通过事务消息能达到分布式事务的最终一致。
    定时消息:
    就是延迟消息,消息投递到 broker之后不会被真正消费,只有到达指定时间之后才去消费, 具体实现大概如下 这些消息全部投递到 SCHEDULE_TOPIC_XXXX 的topic中 , 并按照延迟时间录入到不同的 queue中,broker会调度消费这些queue 再投递到真正的topic中。以上相同延迟的消息会放入一个queue,保证相同延迟消息的消费顺序性。

消息重试:
kafka消息消费的时候,默认是自动提交offset机制,可能导致消费失败了, 但是 offset已经提交了, 故这属于最多一次语义。但是要实现至少一次语义则必须消息队列实现消息重试机制。
重试场景如下:

  1. 业务错误比如手机号码注销了, 充值肯定充不进去,此时即使重试也不管用, 最好办法是 比如3S 之后再重试
  2. 比如DB 不可用了, 此时即使跳过, 消费其他的也还是不可用,所以最好的办法是sleep 30S
    RocketMQ会为每个消费组都设置一个Topic名称为“%RETRY%+consumerGroup”的重试队列, 这个重试队列是针对消费组的,用于暂时保存因为各种异常而导致Consumer端无法消费的消息。考虑到异常恢复起来需要一些时间,会为重试队列设置多个重试级别,每个重试级别都有与之对应的重新投递延时,重试次数越多投递延时就越大。RocketMQ对于重试消息的处理是先保存至Topic名称为“SCHEDULE_TOPIC_XXXX”的延迟队列中,后台定时任务按照对应的时间进行Delay后重新保存至“%RETRY%+consumerGroup”的重试队列中。

消息重投:
当生产者投递消息失败时会发起,保证消息不丢失, 尽可能成功,但是会造成消息重复。当出现数据量大网络抖动的时候,重复投递是大概率事件,比如由于网络抖动,ACK失败,但是消息实际已经落盘了。另外生产者主动重发、消费者挂了, 触发新的负载均衡也会导致消息重复。

死信队列:
消费者消费失败,broker自动进行重试还是失败, broker就会把它投递到死信队列, 消息不会丢失。这条消息就叫做死信队列。

架构设计

https://github.com/apache/rocketmq/blob/master/docs/cn/architecture.md
NameServer 是全分布式的、平等部署的, produce注册的时候是向所有的NameServer广播注册, 其中任何一台挂了, 都没啥问题, 算是彻底解决了单点问题。
Broker 属于 一个master对应多个 Slave 架构。多个slave 是只读的可以分摊读的压力。

设计(design) 关键核心技术实现细节,比较复杂

https://github.com/apache/rocketmq/blob/master/docs/cn/design.md

样例

https://github.com/apache/rocketmq/blob/master/docs/cn/RocketMQ_Example.md

  • 生产者
    • 同步发送,这种可靠性同步地发送方式使用的比较广泛,比如:重要的消息通知,短信通知。
    • 异步发送 callback,异步消息通常用在对响应时间敏感的业务场景,即发送端不能容忍长时间地等待Broker的响应。
    • 单向发送消息, 不用管发送的结果,比如 日志发送
    • 生产的时候自定义属性,message putUserProperty
  • 消费消息
    • 普通消费
    • 顺序消息样例: 2种方式全局有序, queue内有序(发送时指定按照那个KEY进行hash)
    • 延时消息 发送消息时指定 delayTimeLevel
    • 批量消息,能显著提高传递小消息的性能,限制是这些批量消息应该有相同的topic,相同的waitStoreMsgOK,而且不能是延时消息。此外,这一批消息的总大小不应超过4MB。
    • 当消息过大时需要执行消息列表分割
    • 过滤消息样例
      • 按照 TAG 进行过滤
      • 订阅消息时,使用 用MessageSelector.bySql来使用sql筛选消息
  • 事务消息
    • 事务消息共有三种状态,提交状态、回滚状态、中间状态:
    • 生产消息的时候需要指定 transactionListener
      • executeLocalTransaction 当半消息发送成功之后回调
      • checkLocalTransaction broker 周期性回调 check消息最终状态,使用 produce 定义的线程池去执行
  • OMSProducer 本质上属于 openAPI的方式进行调用

最佳实践

参考:
https://github.com/apache/rocketmq/tree/master/docs/cn

posted on 2021-11-05 15:55  踏雪扬尘-wx  阅读(119)  评论(0编辑  收藏  举报