【重新理解通信模型】Reactor 模式在 Redis 和 Kafka 中的应用

重新理解通信模型

每个框架都有自己的通信模型,用于处理网络事件。只是不同的框架依据自身的侧重点,对网络通信的要求和实现方式不一样。

我们的网络通信模式发展历程:

  • 单线程:一次只能处理一个请求,其他请求阻塞,处理效率低;
  • 多线程:一个请求一个连接,大量的创建线程,带来线程切换和维护问题,系统复杂度高;
  • 线程池:线程复用,线程管理,但是线程池资源有限,也有线程等待问题。
  • Reactor:现代高性能网络 IO 模式,利用事件驱动机制。

0,Reactor

Reactor 模式,反应堆模式,是一种以事件驱动的网络请求处理模式,在许多高性能网络通信框架中都有实现。

在 Reactor 模式中,将网络处理请求分为一个个事件,具体包括读事件、写事件、连接事件。

该模式下,有三个关键组件:reactor、acceptor、handler,分别对应着监听并分发请求,连接请求和处理请求。
单reactor单线程模型

基本流程:客户端请求首先都被 reactor 接收,reactor 根据请求类型将请求分发,对于连接请求会分发到 acceptor 组件,他时刻监听者网络状态,对于读请求和写请求则交给 handler 处理。

同时,按照处理方式的不同,reactor 模式又可以分为多种:

单 reactror 单线程:一个 reactor,一个 handler;

缺点:单线程,处理能力慢(相较于这三者来说),redis6.0 以前采用这种方式,比如 keys * 就容易阻塞

单 reactror 多线程:一个 reactor,handler 将请求丢到 worker 线程池,读写事件由线程池处理

充分利用多核能力,redis6.0 引入的多线程机制就是这种模式,但是 redis 具体命令执行的逻辑仍然是单线程。

多 reactor 多线程:mainReactor 负责 acceptor 处理,subReactors 负责 handler 处理

可以看到性能非常强悍了,kafka,netty 都有使用到这种模式。

1,Redis 中的 Reactor

redis 中 reactor 模式的体现是在 IO 多路复用基础上实现的,具体来说 redis 针对不同 os 的 IO 多路复用机制实现了不同的 reactor 模型,比如 mac os 的 kqueue;我们主要说下 Redis 基于 Linux 的 epoll 函数实现的 reactor 模式。注意:只有 epoll 采用了事件驱动的思想。

那 redis 是如何复用 epoll 的呢?

首先通过一个 while 循环不断监听网络事件,根据事件的不同执行不同的处理策略。主要有三类事件,空事件,继续轮询;时间事件,调用时间处理函数;读写事件,这时就需要调用 os 的 io 多路复用机制执行事件捕获了。这里简单提一下多路复用函数 epoll 的工作流程:

epoll 首先通过 epoll_ctl 函数注册一个文件描述符,并监听其他文件描述符状态,如果某个 fd 就绪,便会采用回调机制 callback,激活这个 fd 并把它放到就绪列表中,然后由具体的线程处理。

2,Kafka 中的 Reactor

kafaka 中也依据 Reactor 模式设计了自己的网络通信框架,底层使用 NIO 中的 selector 函数。
在这里插入图片描述

首先,broker 中有个 stockerserver 会监听并分派请求,acceptor 处理连接请求,并轮旋选择一个 processor 处理这个连接。这个网络线程处理由参数 num.network.threads=3 控制。然后在 IO 线程中由 work 线程具体执行,num.io.threads=8。执行完之后,会将 reponse 放到响应队列中,然后返回到客户端。其中,每个网络线程都有自己的响应队列。

除此之外,kafka 增加了一个缓存层,RequestChannel,用来缓存那些延时请求,用来处理设置了 ack=all 的 produce 请求

源码中的一些细节:

#SocketServer,管理了两套 acceptor,processor,RequestChannel;包括数据请求 data-plane,控制请求 control-plane;

#KafkaRequestHandlerPool,IO 线程池,实际处理请求的线程,KafkaRequestHandler 匹配并处理不同的请求。
在这里插入图片描述
kafka 的请求过程就是网络通信的过程,这里再提一下,为了处理不同的请求,kafka 将请求设置了优先级。分为

数据请求:如 produce 请求,将消息写入到磁盘;fetch 请求,从磁盘或缓存页拉取消息

控制请求:如更新副本及 ISR 的 leaderAndlsr 请求,以及勒令副本下线的 stopReplica 请求等

请求优先级的好处是,可以优先处理部分请求,防止无效的请求处理。比如,在删除主题时,我们会使用 stopreplica 请求,这样即便是 ack=all 的情况下,也无需等待 ack 全部完成,即可执行删除请求,加快了处理速度,避免了无效操作。实现机制是,启动上面提到的两套请求处理模型,并配置不同的 listeners 监听该请求,然后显示指定。

参考链接:

select、poll、epoll 的详细分析

reactor 模式介绍及分类

Redis 中 reactor 模式详解和源码分析

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值