赞
踩
消息队列概念举例
小红是小明的姐姐,小红为了督促小明多读书,经常寻找好书给小明看,先前的方式是这样的,小红先问小明什么时候有空,然后把书送到小明跟前并且监督小明读完书再离开,久而久之,两人都有些厌烦,可书还是要读的,否则怎么跳槽加薪啊?
所以改变了方式,小红把小明需要看的书都放到书架上,小明直接从书架上拿下来书看即可,这时书架就是一个消息队列,小红是生产者,小明是消费者,这样做带来了四大好处
消息队列解决的问题
解耦:消息队列要解决的最本质问题,你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束即可,而不需要直接调用他人的接口,大大降低耦合度;如下图,消息队列诞生前B需要A找那个的数据只能掉A中的接口,后续更多的服务器B1,B2掉用了A接口,那就产生接口耦合了
案例中的三人(今后读书小组可能还会发展到n人的规模)不必受其它成员时间和习惯等因素的影响,只通过一个简单的书架来进行联系,他们眼里只有书架没有其它人,甚至后期小红都不关心谁来取书看,读书者们也不关心谁把书放到书架上的,和一个简单的消息队列打交道显然比和一个个人打交道简单的多
广播(发布订阅模式):消息队列的基本功能之一。有了消息队列,我们只需要关心消息是否送达了队列,至于谁希望订阅,是下游的事情,无疑极大地减少了开发和联调的工作量。这里小红只需一个简答的放书动作就能使读书小队人人都能读书
错峰与流控:讲用户请求存储在kafka,消费端也就是服务器端定额拉去处理请求,如果因为短暂的流量激增(比如秒杀业务和双11等场景)而扩展服务器那无疑是一种巨大的浪费,这样用于流量削峰场景,起到一个缓冲的作用。小红猛然发现一堆好书,此时如果还是采用之前的方法督促小红去完成小明会裂开,因为小明的读书能力和精力都是有限的,妈妈(用户)也很因为小明完不成任务恼怒,但有了书架后,小红就随缘了,把这一堆书放到书架上即可,并且会给妈妈打一个招呼,让小明慢慢看去吧,虽然速度还是那样,但总比小明累死强啊。
恢复性:系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
最终一致性:两个系统的状态保持一致,要么都成功,要么都失败。最终一致性不是消息队列的必备特性,但可以依靠消息队列来做最终一致性。小红在书架上按个监视器,因为最终目的是要让小明把书读完的,而不是简单的把书放到书架上,小红通过监视器能知道小明的读书情况,大部分情况下小明肯定是能正常完成任务的,但也不排除一些意外如书丢了或者书错了导致小明没有成功读完书,小红也能知道小明没有完成任务
异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许生产者把一个消息放入队列,但消费者并不立即处理它。生产者想向队列中放入多少消息就放多少,然后消费者在需要的时候再去处理它们。小明突然身体不舒服不想读书,难道小红还要等小明身体回复再监视他读完吗?并不是这样,我们只需要让小明立一个FLAG,然后小红把这个flag汇报给妈妈(公司用户),让妈妈知道至少小明是有这个意愿读书的,等小明身体恢复就会立刻爬起来读书。
总结
kafka优点
kafka缺点
1 引入复杂度,书架本身就是多出来的
2 暂时不一致,其实最终一致性和展示不一致性是同一概念,先前的方式小红监督小明读书,虽然费劲,但如果妈妈问小红小明的读书情况那么小红可以理直气壮的说小明读完了or没读完,但现在小红只能模糊的回答:应该读完了或者快读完了,也就是说中间存在一段时间就是我们认为小明已经读完了,但其实小明正在阅读还没读完,但最终小明会读完的,这就是最终一致性
3 无法获取反馈,采用这种方式可以看出来小红
消息队列的特征
1 应用场景
2数据可靠性
由于RocketMQ支持同步刷盘和同步Replication,所以可靠性较高。但对于kafka就算异步刷盘,当broker挂掉时,数据是不会丢失的,只有系统crash才会造成丢失,但是在集群模式下,可以设置同步replication,如果是同步replication,复制因子为N,允许N-1个服务所
在的系统crash,而不会丢失数据
3 性能对比
4单机支持的队列数
队列多有什么好处?
单机可以创建更多Topic,因为每个Topic都是由一批队列组成,Consumer的集群规模和队列数成正比,队列越多,Consumer集群可以越大
5 消息投递实时性
Kafka的consumer端不支持push被动接收消息,只支持pull主动拉去消息,如果使用短轮询方式,实时性取决于轮询间隔时间,实时性较弱,后续版本推出了长轮询增强了实时性,长轮询会造成资源浪费,所以新版本kafka会有一个timeout参数,如果timeout时间内都没有producor向kafka发送的新消息,那么bkafka就会暂停一段时间再次进行拉取,减少资源消耗
RocketMQ的conusmer端同时支持push和pull两种消息获取形式,使用长轮询,同Push方式实时性一致,消息的投递延时通常在几个毫秒。
6 消费失败重试
Kafka先前消费失败不支持重试,后期支持
message.send.max.retries=100
retry.backoff.ms=5000
不过这个重试时间是固定的,通常希望有个倍数。消息不丢失主要依赖ack机制,但是可能会造成重复,这个消息中间件通常希望通过业务来解决,最简单的办法,表中设置一个唯一键,或者写业务数据的同时,增加一张日志表,保证唯一。
ack机制:
RocketMQ消费失败支持定时重试,每次重试间隔时间顺延
总结:例如充值类应用,当前时刻调用运营商网关,充值失败,可能是对方压力过多,稍后在调用就会成功,如支付宝到银行扣款也是类似需求。
这里的重试需要可靠的重试,即失败重试的消息不因为Consumer宕机导致丢失。
消息顺序
Kafka支持消息顺序,但是一台Broker宕机后,就会产生消息乱序
RocketMQ支持严格的消息顺序,在顺序消息场景下,一台Broker宕机后,发送消息会失败,但是不会乱序
定时消息
Kafka不支持定时消息
RocketMQ支持两类定时消息
开源版本RocketMQ仅支持定时Level
阿里云ONS支持定时Level,以及指定的毫秒级别的延时时间
分布式事务消息
Kafka不支持分布式事务消息
阿里云ONS支持分布式定时消息,未来开源版本的RocketMQ也有计划支持分布式事务消息
虽然kafka不支持分布式事务,但是大多互联网应用采用分布式事务的很少,主要是因为
Kafka有两个等级的api,大多使用highLevel的,还有一个simple Api,可以自己控制offset的存储,这样就可以变向实现分布式事务了。
消息查询
Kafka不支持消息查询
RocketMQ支持根据Message Id查询消息,也支持根据消息内容查询消息(发送消息时指定一个Message Key,任意字符串,例如指定为订单Id)
消息查询对于定位消息丢失问题非常有帮助,例如某个订单处理失败,是消息没收到还是收到处理出错了。
但是没人在意日志中那一条数据有问题,比较实用
消息回溯
Kafka理论上可以按照Offset来回溯消息
RocketMQ支持按照时间来回溯消息,精度毫秒,例如从一天之前的某时某分某秒开始重新消费消息
典型业务场景如consumer做订单分析,但是由于程序逻辑或者依赖的系统发生故障等原因,导致今天消费的消息全部无效,
需要重新从昨天零点开始消费,那么以时间为起点的消息重放功能对于业务非常有帮助。
消费并行度
kafka:Consumergroup:各个consumer(consumer 线程)可以组成一个组(Consumer group ),partition中的每个message只能被 组(Consumer group ) 中的一个consumer( consumer 线程 )消费,如果一个message可以被多个 consumer( consumer 线程 ) 消费的话,那么这些consumer必须在不同的组。Kafka不支持一个partition中的message由两个或两个以上的同一个consumer group下的consumer thread来处理,除非再启动一个新的consumer group。所以如果想同时对一个topic做消费的话,启动多个consumer group就可以了,所以Kafka的消费并行度依赖Topic配置的分区数,一个分区只能被消费者中的一个消费者线程消费,比如分区数为10,那么一个消费者组最多10个消费者,大于10的部分就浪费掉了,但无论消费者组消费者数目多么少,哪怕只有一台机器,这一台机器也能消费掉全部的partition,也就是所有的分区都会一个不漏的被消费掉,最优的设计就是consumer group下的consumer thread的数量等于partition数量,这样效率是最高的。扩展策略:如果觉得效率不高的时候,可以加partition的数量来横向扩展,再加新的consumer thread去消费,如果想多个不同的业务都需要这个topic的数据,起多个consumer group就好了
那么最多10台机器来并行消费(每台机器只能开启一个线程),或者一台机器消费(10个线程并行消费)。即消费并行度和分区数一致。
RocketMQ消费并行度分两种情况
顺序消费方式并行度同Kafka完全一致
乱序方式并行度取决于Consumer的线程数,如Topic配置10个队列,10台机器消费,每台机器100个线程,那么并行度为1000。
消息轨迹
Kafka不支持消息轨迹
阿里云ONS支持消息轨迹
Broker端消息过滤
Kafka不支持Broker端的消息过滤
RocketMQ支持两种Broker端消息过滤方式
根据Message Tag来过滤,相当于子topic概念
向服务器上传一段Java代码,可以对消息做任意形式的过滤,甚至可以做Message Body的过滤拆分。
消息堆积能力
理论上Kafka要比RocketMQ的堆积能力更强,不过RocketMQ单机也可以支持亿级的消息堆积能力,我们认为这个堆积能力已经完全可以满足业务需求。
架构对比
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。