谈一谈我与分布式消息的那些事(上)
在互联网应用实践中,缓存和消息,是必然会被提到的基础类服务。本文主要谈分布式消息的相关内容。
先说说消息中间件是用来干嘛的?简单说,就是指软件对象之间进行交互作用和通讯利用的一种方式。
什么是消息通讯?由于历史原因,及技术特点不同,我们公司共用到两种三种不同的消息中间件选型:
1、ActiveMQ
用途:应用数据或通知机制
2、RocketMQ
用途:应用数据或通知机制
3、Kafka
用途:日志传输、采集、分发
以下是ActiveMQ与RocketMQ的简要拓扑图:
图2. 简要拓扑图一、基于消息通讯的应用场景
我常说,技术的存在是因为应用场景的需要,绝非是一种装逼的体现。
所谓 “存在即合理”,下面我简单陈述一下,在我现有公司中的几种消息通讯的应用场景。
1)数据传输 - 主键(或核心)
场景说明:
1、基金业务需要每个交易日收盘后进行清算。
2、在A系统在进行基金交易清算过程中,会逐步将已完成的“基金公司TA编号”、“基金产品编号” 等主键数据,通过MQ传输到中台F系统。
3、F系统接受到数据后,基于 “基金公司TA编号”、“基金产品编号” 等主键数据,通过调用后台B系统、C系统的某些接口,完成所需逻辑。
为什么要这么做?
主要是为了解耦,因为我们把后台系统定义为标准服务层,中台系统定义为应用编排层,这样设计1是为了防止 “层级接口回调”,2是与数据解耦。
2)数据传输 - 增量(或全量)数据
场景说明:
1、用户中心的用户标签,由大数据系统(离线)计算完成之后,将增量数据通过MQ同步到接口服务系统,持久化之后,由接口的方式供其他系统调用。
2、短信、微信通过消息给到消息中心进行发送。
3、资产清算,通过分布式算法,将不同的数据通过消息推送到计算节点,进行分布式计算
3)状态通知
场景说明:
1、B系统通过MQ传输状态,但数据中只有状态,不包含其他,比如 “我已完成”;
2、A系统接收到状态后,向B系统发起接口调用请求;
以上这三种场景是目前我们系统使用MQ最常见的方式,也许有人会觉得非常不合理,或者牛刀杀鸡,我们不在这里讨论,当前只陈述现状。
二、Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别?
消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。
三、RocketMQ与kafka对比
1)数据可靠性
RocketMQ - 支持异步实时刷盘,同步刷盘,同步复制,异步复制
Kafka - 使用异步刷盘方式,异步复制/同步复制
总结:RocketMQ的同步刷盘在单机可靠性上比Kafka更高,不会因为操作系统Crash,导致数据丢失。Kafka同步Replication理论上性能低于RocketMQ的同步Replication,原因是Kafka的数据以分区为单位组织,意味着一个Kafka实例上会有几百个数据分区,RocketMQ一个实例上只有一个数据分区,RocketMQ可以充分利用IO组Commit机制,批量传输数据,配置同步Replication与异步Replication相比,性能损耗约20%~30%,Kafka没有亲自测试过,但是个人认为理论上会低于RocketMQ。
2)性能对比
Kafka - 单机写入TPS约在百万条/秒,消息大小10个字节
RocketMQ - 单机写入TPS单实例约7万条/秒,单机部署3个Broker,可以跑到最高12万条/秒,消息大小10个字节
总结:Kafka的TPS跑到单机百万,主要是由于Producer端将多个小消息合并,批量发向Broker。
RocketMQ为什么没有这么做?
3)单机支持的队列数
Kafka - 单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,load越高,发送消息响应时间变长。
RocketMQ - 单机支持最高5万个队列,负载不会发生明显变化
4)消息投递实时性
Kafka - 使用短轮询方式,实时性取决于轮询间隔时间,0.8以后版本支持长轮询。
RocketMQ - 使用长轮询,同Push方式实时性一致,消息的投递延时通常在几个毫秒。
5)消费失败重试
Kafka - 消费失败不支持重试。
RocketMQ - 消费失败支持定时重试,每次重试间隔时间顺延。
总结:例如充值类应用,当前时刻调用运营商网关,充值失败,可能是对方压
力过多,稍后再调用就会成功,如支付宝到银行扣款也是类似需求。
这里的重试需要可靠的重试,即失败重试的消息不因为Consumer宕机导致丢失。
6)严格的消息顺序
Kafka - 支持消息顺序,但是一台代理宕机后,就会产生消息乱序
RocketMQ - 支持严格的消息顺序,在顺序消息场景下,一台Broker宕机后,发送消息会失败,但是不会乱序
6)定时消息
Kafka - 不支持定时消息
RocketMQ - 支持两类定时消息
7)分布式事务消息
Kafka - 不支持分布式事务消息
阿里云MQ支持分布式事务消息,未来开源版本的RocketMQ也有计划支持分布式事务消息
8)消息查询
Kafka - 不支持消息查询
RocketMQ支持根据消息标识查询消息,也支持根据消息内容查询消息(发送消息时指定一个消息密钥,任意字符串,例如指定为订单编号)
总结:消息查询对于定位消息丢失问题非常有帮助,例如某个订单处理失败,是消息没收到还是收到处理出错了。
9)消息回溯
Kafka - 理论上可以按照偏移来回溯消息
RocketMQ - 支持按照时间来回溯消息,精度毫秒,例如从一天之前的某时某分某秒开始重新消费消息
总结:典型业务场景如consumer做订单分析,但是由于程序逻辑或者依赖的系统发生故障等原因,导致今天消费的消息全部无效,需要重新从昨天零点开始消费,那么以时间为起点的消息重放功能对于业务非常有帮助。
10)消息堆积能力
理论上Kafka要比RocketMQ的堆积能力更强,不过RocketMQ单机也可以支持亿级的消息堆积能力,我们认为这个堆积能力已经完全可以满足业务需求。