聊聊Redis的单线程模型

作者:nimo10050 时间:2022-02-21 09:20:42 

开篇

本文主要来探讨一下 redis 的单线程模型,文章前半部分会先引用某网络课程讲解的内容(图片+语言描述),后半部分是本人粗略阅读 redis 源码后整理出来的一份伪代码,用来验证文中前半部分的内容。

本文对标的 redis 版本是 5.x。

redis 涉及的知识点有很多,展开来讲能聊到操作系统,因此为了方便理解,文中做了很多抽象描述。

文件事件处理器

redis 内部使用了一个叫 文件事件处理器( file event handler)的东西,这个文件事件处理器是 单线程 的,所以才有了 redis 是单线程的这一说法。

文件事件处理器的结构如下图:

聊聊Redis的单线程模型

它包含 4 个部分:

  • 多个 socketIO

  • 多路复用程序

  • 文件事件分派器

  • 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

文件事件处理器 采用 IO 多路复用机制 同时监听多个 socket,根据 socket 上的事件来选择对应的事件处理器进行处理。多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序 会监听多个 socket,会将 socket 产生的事件放入 队列 中排队,事件分派器 每次从队列中取出一个事件,把该事件交给对应的 事件处理器 进行处理。

来看 redis 客户端与服务端的一次通信过程:

聊聊Redis的单线程模型

1. 接收连接请求:

客户端 socket01 向 redis 的 server socket 请求建立连接,此时 server socket 会产生一个 AE_READABLE 事件,

IO 多路复用程序监听到 server socket 产生的事件后,将该事件压入队列中。

文件事件分派器从队列中获取该事件,交给连接应答处理器。

连接应答处理器会创建一个能与客户端通信的 socket01,并将该 socket01 的 AE_READABLE 事件与 命令请求处理器 关联。

2. 读取请求内容:

假设此时客户端发送了一个 set key value 请求,此时 redis 中的 socket01 会产生 AE_READABLE 事件

IO 多路复用程序将事件压入队列

事件分派器从队列中获取到该事件,由于前面 socket01 的 AE_READABLE 事件已经与命令请求处理器关联,因此事件分派器将事件交给命令请求处理器来处理。

命令请求处理器读取 socket01 的 key value 并在自己内存中完成 key value 的设置。操作完成后,它会将 socket01 的 AE_WRITABLE 事件与命令回复处理器关联。

3. 回复请求:

如果此时客户端准备好接收返回结果了,那么 redis 中的 socket01 会产生一个 AE_WRITABLE 事件,同样压入队列中,

事件分派器找到相关联的命令回复处理器

由命令回复处理器对 socket01 输入本次操作的一个结果,比如 ok,之后解除 socket01 的 AE_WRITABLE 事件与命令回复处理器的关联。

这样便完成了一次通信。

redis 事件处理伪代码

// 入口函数
void aeMain(EventLoop eventLoop) {
   while(true) {
   // 文件事件处理器
   aeProcessEvents(eventLoop);  
   }
}
void aeProcessEvents() {
// 调用 epoll_wait 函数,等待I/O事件 (IO 多路复用程序)
   int numevents = aeApiPoll(timeval);
   for(int i=0; i< numevents; i++) {
   // 从队列中取出对应的事件
   fileEvent = getFromEventQueue(i);
   // 处理文件事件(文件事件分派器)
   processFileEvent(fileEvent);
   // 处理时间事件。(忽略)
   processTimeEvent();
   }
}
void processFileEvent() {
if event == '读事件' {
// 读处理器
processReadFile();
}
if event == '写事件' {
// 写处理器
processWriteFile();
}
}

redis 源码

篇幅原因这里就不贴 redis 的源代码,可以用 vscode 等工具打开 redis 安装目录下的 src 目录,通过全局搜索 aeMain 找到入口。

来源:https://blog.csdn.net/cnm10050/article/details/110069606

标签:Redis,单线程,模型
0
投稿

猜你喜欢

  • Android动态修改ToolBar的Menu菜单示例

    2021-10-29 15:36:07
  • SpringBoot中异常处理实战记录

    2022-07-21 20:39:01
  • Android下Activity全屏显示实现方法

    2022-12-17 19:57:56
  • 浅谈Springboot之于Spring的优势

    2022-01-08 02:35:29
  • java实现快速排序图文详解

    2022-10-11 16:35:18
  • c# Thread类的用法详解

    2023-02-08 06:53:28
  • C#使用iTextSharp封装的PDF文件操作类实例

    2023-05-16 22:26:52
  • C#窗体布局方式详解

    2023-09-26 11:17:32
  • Android实现双击返回键退出应用实现方法详解

    2023-03-23 21:33:29
  • Android开发之自定义刮刮卡实现代码

    2023-07-30 14:52:57
  • SpringBoot使用validation-api实现参数校验的示例

    2022-12-02 14:33:40
  • SpringMVC的源码解析

    2022-10-05 20:12:18
  • SpringCloud学习笔记之OpenFeign进行服务调用

    2021-05-25 12:32:58
  • Android Studio编写AIDL文件后如何实现自动编译生成

    2022-01-25 16:44:38
  • C#实现窗体抖动的两种方法

    2021-10-06 10:20:52
  • Android 自定义一套 Dialog通用提示框 (代码库)

    2022-10-08 06:20:31
  • Java实现简单的抽牌游戏

    2022-10-06 11:55:01
  • C#使用表达式树(LambdaExpression)动态更新类的属性值(示例代码)

    2022-05-17 11:46:16
  • C#图像处理之边缘检测(Sobel)的方法

    2022-05-12 02:05:50
  • C# DateTime与时间戳转换实例

    2022-12-12 08:34:12
  • asp之家 软件编程 m.aspxhome.com