消息中间件设计——解耦业务系统与核心系统
同步和异步
什么是同步?什么是异步?
同步与异步指的是消息通信机制
同步 在发出一个调用后 没有得到的结果之前,该调用不返回,即调用者主动等待这个调用的结果。
异步 与同步相反,在调用发出后直接返回结果。即在一个异步调用发出后,调用者立刻去做其他事情。
为什么需要消息中间件?
业务系统和核心系统的交互比较频繁,系统之间耦合度太高。核心系统和业务系统有很多重复的开发工作。所以此时需要对它们进行解耦,让各个业务系统能健康的发展。
- 什么是消息中间件,有什么作用?
- 消息中间件就是一个开发好的系统,可以独立部署,业务系统通过它来发消息和收消息。以达到异步调用的效果。
- 消息中间件 可以提升系统性能。
- 系统解耦
- 大流量消峰
生产级消息中间件的选型?
kafka的优缺点
- 支持高吞吐量
- 性能较高
- 支持集群部署
- 有可能丢失数据
- 功能比较单一
RabbitMQ的优缺点
- 能保证不丢失数据
- 能保证高可用
- 支持很多高级功能 如重试、死信队列。
- 吞吐量比较低
- 集群线性扩展比较麻烦
- 开发语言是Erlang
RocketMq的优缺点
- 吞吐量很高
- 能保证高可用、高性能
- 保证数据绝对不丢失
- 支持大规模集群部署,线性扩展方便
- 支持各种高级功能,如延迟消息,消息回溯等
- 支持各种高级功能,如延迟消息,消息回溯等
- 基于Java语言的开发,能满足 国内绝大部分公司技术栈。
RocketMQ架构原理
NameServer 和bROKER
NameServer是RocketMQ的路由中心,主要提供管理、服务注册及服务发现功能。
Broker是由RocketMQ的核心模块,主要提供消息的接受、存储和拉取等功能
如何保证高可用?
1.RocketMQ中的数据是分布式存储在Broker中的,如果右节点宕机,那么RocketMQ是如何保证数据不丢失的呢?
- 采用多副本的方式,RocketMQ采用主从架构及多副本策略,来保证Broker数据的高可用
NameServer如何感知Broker的健康状态。
- Broker在启动后会自动向所有的NameServer急求你注册,这样所有的NameServer节点都知道了这个Broker。业务系统可以通过Nameserver集群拉取Broker,从而进行消息的发送/获取。
引入消息中间件会带来什么问题?
利用消息中间件能解决系统的各种瓶颈问题,但也会提高系统的复杂度,所以需要解决消息中间件自身的各种问题,这可能会导致降低系统的可用性及稳定性。
RocketMQ的高可用方法
RocketMQ主要采用镜像集群模式来保证高可用,能够百分之百保证数据不丢失。与RabbitMQ的普通集群模式不同,在RabbitMQ的镜像集群模式下,所创建队列queue中的消息及元数据都存在多个RabbitMQ实例上。即在所有的RabbitMQ节点上都有这个queue的完整镜像,在写入消息时会将消息同步到多个mirror queue中。
优点: 在任何一台机器宕机,其他机器还保留了queue的完整消息数据,这样Consumer就可以去其他好的节点上消费信息。
缺点: 性能开销较大,因为消息需要同步到所有节点,所有网络传输消耗很大
kafka的高可用方案
kafka由多个Broker组成,每个Broker就是一个节点。一个Topic可用被划分为多个Partition。Partition可用存在于不同的Broker节点上,每个Partition只存放一部分数据。
如何保证消息不被重复消费?
要完全避免重复消费消息是很难做到的,因为网络的抖动、机器的宕机和处理的异常都是难以避免的。
- 生产过程中 可用给每个生产者定义一个唯一的ID
- 给生产的每一条消息 定义一个唯一的ID
- 消息中间件服务端村消息时,存储生产者ID与最后一条消息ID映射。如果在生产出一条新消息后,消息中间件服务端会先将消息ID与其存储的最后一条消息ID进行对比。如果相等 则是重复消息 。如果不相等,则进行存储。
- 消费过程中
- 给消息生成一个唯一的ID,在消息消费后将数据ID存到数据库中
- 在消费下一条消息前,现在数据库中查询是否有这个消息ID,如果有则是重复消息,不处理。
如何保证消息的顺序性?
在Topic中,一个Partition对应一个Consumer,只能单线程消费。对性能及并发要求稍微高的场景中就很不合适了,因为单线程吞吐量效率太低。
- 在消费端程序中写多个内存队列
- 将相同key的消息数据放在同一个内存队列中
- 在多线程消费时,每个线程对一个内存队列进行消费
消息中间件中的消息延迟?
- 监控消息中间件中的消息延迟
- 开发消息监控程序
- 减少消息中间中的消息延迟
- 优化消费代码以提升性能
- 增加消费者数量