MQ基础介绍
核心概念
- Topic
- 生产者
- 消费者
- 消息属性:生产者可以为消息定义的属性,包含
Message Key
和Tag
。 - Group:一类生产者或消费者,这类生产者通常生产或消费同一类消息,且消息发布或订阅的逻辑一致。
消息类型
- 普通消息
- 事务消息:实现类似X/Open XA的分布事务功能,以达到事务最终一致性状态。
- 定时和延时消息:允许消息生产者对指定消息进行定时(延时)投递,最长支持40天。
- 顺序消息:允许消息消费者按照消息发送的顺序对消息进行消费。
MQ应用场景
- 交易系统
- 红包秒杀
- 关闭未支付订单
- 用户信息注册
- 在线抽奖设计
- 任务系统设计
- 跨区域数据同步
- 异步解耦
- 消峰填谷
- 分布式事务消息
- 大数据分析
- 分布式模缓存同步
- 异步系统
- …
MQ产品发展路线
- 2003 activeMQ
- 2006 rabbitMQ
- 2010 kafka 2010
- 2011 RocketMQ
- 2012 Pulsar
MQ存在的意义
为什么需要MQ?
直接调用服务接口不行吗?
优点
-
异步性
异步化处理,减少了同步等待的时间。 -
松耦合
通过消息队列进行通信,不同关心彼此的实现细节,只要定义好消息的格式就行。 -
分布式
可以通过对消费者的横向扩展,降低了消息队列阻塞的风险,以及单个消费者缠上单点故障的可能性。(当然消息队列本身也可以做成分布式集群) -
可靠性
消息对垒一般会把接收到的消息储存到本地硬盘上(当消息被处理完之后,储存信息根据不同的消息队列实现,有可能将其删除),这样及时应用挂掉或者消息队列本身挂掉,消息也能够重新加载。
缺点
-
可用性
万一MQ炸了呢,可用性就没了。 -
复杂性
需要考虑一些消息队列的常见问题和解决方案 -
一致性
多个消费者消费,万一有一个消费者失败了,就会数据不一致。
如何保证消息队列的高可用性?
如何保证消息的可靠性传输?
使用事务的方式来确保
重试队列与死信队列
RabbitMQ
单机模式
风险大
普通集群模式
这⽅案主要是提⾼吞吐量的,就是说让集群中多个节点来服务某个queue的读写操作。
镜像集群模式
缺点在于性能开销太⼤和扩展性很 低,同步所有实例,这会导致⽹络带宽和压⼒很重,⽽且扩展性很低,每增加⼀个实例都会去包含 已有的queue的所有数据,并没有办法线性扩展queue。
Kafka
分布式队列
- Kafka天⽣就是⼀个分布式的消息队列,它可以由多个broker组成,每个broker是⼀个节点; 你创建⼀个topic,这个topic可以划分为多个partition,每个partition可以存在于不同的 broker上,每个partition就放⼀部分数据。
高可用机制
- Kafka的⾼可靠性的保障来源于其健壮的副本(replication)策略。kafka会均匀的将⼀个 Partition的所有Replica分布在不同的机器上,来提⾼容错性。每个Partition的数据都会同步 到其它机器上,形成⾃⼰的多个Replica。然后所有Replica会选举⼀个Leader出来,那么⽣产 和消费都去Leader,其他副本就是Follower,Leader会同步数据给Follower。当Leader挂了 会⾃动去找Replica,然后会再选举⼀个Leader出来。
副本策略的缺点
- 为了提⾼性能,每个Follower在接收到数据后就⽴⻢向Leader发送ACK,⽽⾮等到数据写⼊ Log中。因此,对于已经commit的消息,Kafka只能保证它被存于多个Replica的内存中,⽽ 不能保证它们被持久化到磁盘中,也就不能完全保证异常发⽣后该条消息⼀定能被Consumer 消费。
如何保证消息消费时的幂等性
重复消费的主要原因
消息重复消费的主要原因在于反馈机制。
消息消费的幂等性
实际上我们只要保证多条相同的数据过来的时候只处理⼀条或者说多条处理和处理⼀条造成的结果 相同即可,但是具体怎么做要根据业务需求来定,例如⼊库消息,先查⼀下消息是否已经⼊库,或 者唯⼀约束之类。
异常信息处理
一定要对消息有明确处理,及时ack。
如何保证消息消费的顺序性?
顺序性
保证消息是按顺序发送,按顺序消费,⼀个接着⼀个。
方案
-
单
topic
,单partition
,单consumer
,单线程消费
吞吐量低,不推荐 -
自定义线程池
拒绝策略都是CallerRunsPolicy,防止消息丢失
Pulsar基本介绍
Pulsar VS Kafka
Pulsar 和 Kafka 都是以 Topic 描述⼀个基本的数据集合,Topic 数据⼜分为若⼲ Partition(分 区),即对数据进⾏逻辑上的 sharding 后存储为若⼲⼦集合。但Kafka 以 partition 作为物理存储 单位,每个 partition 必须作为⼀个整体(⼀个⽬录)存储在某⼀个 broker 上。 ⽽ Pulsar 的每个 partition 是以 segment(对应到 Bookkeeper 的 Ledger) 作为物理存储的单位,所以 Pulsar 中 的⼀个逻辑上有序的 partition 数据集合在物理上会均匀分散到多个 bookie 节点中。 Pulsar 的数据存储节点 Bookkeeper 被称为 Bookie,相当于⼀个 Kafka Broker。 Ledger 是 Topic 的若⼲⽇志的集合,是 Pulsar 数据删除的最⼩单元,即 Pulsar 每次淘汰以 Ledger 为单位进⾏删除。 Fragment 是 Bookkeeper 的概念,对应⼀个⽇志⽂件,每个 Ledger 由若⼲ Fragment 组成。