消息中间件

通信模式与用途:

消息中间件构建了这样的通信模式:一条消息由生产者创建.并被投递到存放消息的队列中.消费者从队列中读取这条消息.于是生产者与消费者完成了一次通信.这种通信模式在现实生活很常见.典型的例子是E-mail通信.

1.异步化:

在未使用消息队列的系统中.一些非必要的业务逻辑以同步方式运行.导致请求处理耗时较大.如图所示.

一个用户请求需要串行的经过ABCD四个服务处理.其中A服务是此业务场景的核心服务.请求处理仅需10ms.BCD服务是非核心服务.请求处理时间分别是200ms 300ms 100ms.所以一个用户的请求需要耗时610ms才能得到响应.

使用消息队列后.A服务可以将请求相关信息写入消息队列.然后直接返回响应消息.而不用关心B C D服务是否已经处理请求.以及是否遇到故障.B C D服务异步的从消息队列中拉取消息进行相关的业务处理.这样用户的请求响应时间被大幅降低到10ms.如图所示.

2.流量削峰:

如图所示.假设A服务1s仅可以处理100个请求.流量高峰时10000QPS会直接击垮A服务.而通过消息队列的形式.A服务可以根据自己的请求处理速度来拉取消息.在整个链路上原来的请求量10000QPS被平滑为100QPS.这就是流量削峰.

3.解耦:

在未使用消息队列时.服务之间的耦合性太强.如果B服务想加入A服务的请求处理流程.则需要在A服务中实现对B服务的RPC逻辑.假设系统中有3个服务.

点赞服务:负责处理用户对文章的点赞请求.主要业务逻辑是为用户和文章建立已点赞的关系记录.

热点服务:根据每篇文章的被点赞次数.给出当前最热门的文章列表.

策略服务:分析每个用户的点赞文章类型.以便可以将同类型的文章推荐给用户.

热点服务和策略服务都想实时获取用户的点赞行为.只能在点赞服务对用户点赞请求的处理逻辑中增加对这两个服务的RPC.如果未来有服务也想要收集用户点赞行为.或者策略服务下线.则需要改造点赞服务.于是所有依赖用户点赞行为的服务都与点赞形成了耦合.

在系统中引入消息队列后.这种耦合关系得到完全解耦.点赞服务将在处理用户点赞请求时顺便将点赞事件发送到消息队列.任何希望收集用户点赞行为的服务只需要被配置成这个消息队列的消费者.而不会对点赞服务有任何影响.

如图所示.通过引入消息队列.点赞服务与其他服务彻底解耦.每个服务的负责人只需要专注于自己的服务.

Kafka的概念和原理:

Kafka是一个分布式 高性能 高可扩展性的消息队列系统.最初由LinkedIn开发.在2010年成为Apache基金会旗下的开源项目.Kafka的主要应用场景是日志收集系统和消息中间件.整体架构如下.

1.Producer(生产者)和Consumer(消费者):

前者生产消息后者消费消息.

2.Topic(主题):

每个发送到Kakfa的消息都有自己的Topic.可以将其理解为消息的类型.生产者发送某Topic的消息.消费者订阅该Topic的消息.

3.Partition(分区):

一个Topic将消息数据分布式的存储在多个Partition中.这个Partition与存储系统的数据分片概念相同.都是将全量数据拆分为多个分区存储.以便实现负载均衡.每个Partition存储的消息都是基于key有序的.不同Partition之间的消息不保证有序.Partition由Broker管理.

4.Broker:

Broker是Kafka的核心.负责接收消息 将消息存储到Partition.以及处理消费者的消费消息逻辑.多个Broker组成Kakfa Cluster(Kakfa集群).Kakfa使用全局唯一的Broker ID为每个Broker编号.

5.Consumer Group(消费者组):

多个消费者实例组成一个Consumer Group.一个Topic对应的消费对象是Consumer Group.

6.ZooKeeper:

负责Kakfa集群元信息的管理工作.将包括Kakfa的生产者 消费者和Broker在内的所有组件在无状态的情况下建立起生产者和消费者的订阅关系.并实现生产者与消费者的负载均衡.

6.1Broker注册:

每个Broker实例都需要把自己的BrokerID Ip地址和端口号注册到ZooKeeper.如果某Broker实例宕机.则ZooKeeper会删除其地址信息.ZooKeeper实现了Kakfa集群的服务发现功能.

6.2Topic元信息管理:

一个Topic会创建多个Partition并分布在多个Broker上.每个Topic的Partition与Broker的关联关系也由ZooKeeper维护.

6.3生产者负载均衡:

每个生产者都需要决定它生产的消息应该被写入哪个Partition.由于ZooKeeper中保存了Broker地址信息与Topic元信息.因此生产者可以根据ZooKeeper实现消息写入的负载均衡.

6.4消费者负载均衡:

Kakfa规定一个Partition消息只能被Consumer Group中的一个消费者实例消费.ZooKeeper负责记录"哪个消费者实例消费哪个Partition消息"这样的消费关系.另外.当某个消费者实例宕机后.ZooKeeper可以对相应的Consumer Group做Rebalance.以保证每个Partition消息一直在被消费.

6.5消费进度Offset记录:

消费者实例在消费Partition消息的过程中.ZooKeeper定时记录消息的消费进度Offset.以便消费者实例重启或Consumer Group发生Rebalance后.可以从之前的Partition Offset位置继续消费消息.不过.这个写功能性能不佳.Kakfa0.9奔奔不再将消费进度Offset保存到ZooKeeper.而是保存到Broker本地磁盘.

当生产者向某个Topic发送消息时.首先要决定将消息存储到哪个Partition.

如果消息指定了Partition.则直接使用它.

如果消息未指定Partition.但是消息设置了Key.则对Key做哈希运算后选出一个Partition.

如果消息既未指定Partition也未指定Key.则轮询选择一个Partition.

然后生产者将消息发送到所选择的Partition对应的Broker节点.Broker节点收到消息后将其顺序写入磁盘.消息写入完成.

消费者以Consumer Group方式工作.一个Consumer Group可以消费多个Topic.一个Topic也可以被多个Consumer Group消费.当某Topic被一个Consumer Group消费时.每个Partition消息只能被一个消费者实例消费.但是一个消费者实例可以消费多Partition消息.

这个限制表明.如果Topic有10个Partition.而Consumer Group有20个消费者实例.那么就有10个实例处于空闲状态.

消费者采用拉取(pull)的方式消费Partition消息.这样才能由消费者自己控制消费的速度.以便实现消息队列的削峰能力.

Kafka高可用:

为了实现高可用性.Kafka允许一个Partition拥有多个消息副本.每个Partition的副本由一个Leader和若干Follwer组成.生产者发送消息实际上写入的是Partition的Leader.而Follower则会周期性的向Leader请求消息复制.以保证Leader与Follower之间的数据一致性.不只是生产者发送消息到Leader.消费者消费的也是Leader中的消息.Follower的用途是作为Leader的数据备份.用于在Leader所在的Broker宕机后接管Partition的读/写.尽可能保证消息不丢失.

需要强调的是.如果一个Partition的所有副本都被存储到同一个Broker上.那么Broker宕机后会造成这个Partition完全不可用.达不到高可用性的效果.所以Kafka会尽可能将一个Partition的每个副本都存储到不同的Broker上.

同步复制:

所有的Follower都已经复制此消息才认为消息写入成功.在这种机制下Leader与Follower数据一致性高.但是一旦某个Follower复制速度太慢或者宕机.就会直接劣化消息写入的性能和可用性.

异步复制:

只要Leader收到消息就认为消息写入成功.并不关心Follower是否已复制此消息.在这种机制下.消息写入的性能高.可用性高.但是数据一致性得不到保证.

Kafka采用的数据复制机制既不是完全的同步复制.也不是完全的异步复制.而是ISR机制.每个Partition的Leader都会维护与其保持数据一直的Follower列表.该列表被称为ISR.如果一个Follower长时间未发起数据复制.或者其数据落后于Leader数据太多.那么Leader会将这个Follower从ISR中移除.在Partition写入消息时.只有ISR中所有的Follower都已确认收到此消息.Leader才认为消息写入成功.Leader会根据Follower状态动态的变更ISR.并将变更结果同步到ZooKeeper.

ISR机制其实是同步复制和异步复制的折中.它可以很好的避免某Follower宕机对消息队列的可用性 性能的影响.也在一定程度上保证了多副本间数据的一致性.

多副本能够保证党Broker发生故障时相关的Partition依然有数据备份.Kafka数据备份如何恢复呢?

Kafka0.8版本引入了Partition Leader选举与故障恢复机制.首先.需要在Kafka集群的所有Broker中选举一个Controller角色.用于负责Partition Leader选举和副本重分配工作.当Leader发生故障时.Controller会将Partition的最新Leader Follower变动通知到相关Broker.Broker选举Controller借助了ZooKeeper的分布式锁能力.哪个Broker先抢到锁.它就是Controller.

Controller帮助Broker进行故障恢复的详细过程如下.

1.某Broker发生故障.与ZooKeeper断开连接.

2.ZooKeeper认为此Broker已下线.于是删除该Broker节点.

3.ZooKeeper通知Controller这个Broker已下线.

4.Controller向ZooKeeper查询哪些Topic Partition的Leader副本由这个Broker负责.得到的结果是受影响的 需要重新选举Leader的Partition.

5.Controller从每个Partition Leader ISR中选择一个Follower.准备将其提升为Leader.

6.Controller将选举结果通知到各相关Broker.

7.被选举出的Follower变为Leader.其他Follower转而向新的Leader复制数据.

语雀地址https://www.yuque.com/itbosunmianyi/xg8vfe?

《Go.》 密码:xbkk 欢迎大家访问.提意见.

相关推荐
都说名字长不会被发现2 小时前
Spring Boot Starter 中间件账号密码加密方案设计与实现
java·spring boot·后端·中间件
瀚高PG实验室19 小时前
java中间件无法连接数据库
java·数据库·中间件·瀚高数据库
之歆1 天前
Day11_Express 深入解析:从中间件到项目实战
中间件·express
码农飞哥1 天前
RocketMQ消费接口设计实战:为什么HTTP回调接口必须吞掉所有异常,始终返回成功?
网络协议·http·中间件·消息队列·rocketmq
硅谷秋水1 天前
物理人工智能的驾驭工程:机器人中间件是驾驭层
人工智能·机器学习·语言模型·中间件·机器人
初中就开始混世的大魔王2 天前
6 Fast DDS-传输层
开发语言·c++·中间件·信息与通信
zwh12984540602 天前
【 Fast-DDS 源码分析(一):架构总览与模块介绍】
中间件·架构
放下华子我只抽RuiKe52 天前
FastAPI 全栈后端(六):中间件与依赖注入
ai·中间件·fastapi·ai编程·qwen·ai大模型·openclaw
初中就开始混世的大魔王2 天前
7 Fast DDS-持久化服务
c++·人工智能·中间件·自动驾驶·信息与通信