聊聊Redis的单线程模型
作者:nimo10050 发布时间:2022-02-21 09:20:42
开篇
本文主要来探讨一下 redis 的单线程模型,文章前半部分会先引用某网络课程讲解的内容(图片+语言描述),后半部分是本人粗略阅读 redis 源码后整理出来的一份伪代码,用来验证文中前半部分的内容。
本文对标的 redis 版本是 5.x。
redis 涉及的知识点有很多,展开来讲能聊到操作系统,因此为了方便理解,文中做了很多抽象描述。
文件事件处理器
redis 内部使用了一个叫 文件事件处理器( file event handler)的东西,这个文件事件处理器是 单线程 的,所以才有了 redis 是单线程的这一说法。
文件事件处理器的结构如下图:
它包含 4 个部分:
多个 socketIO
多路复用程序
文件事件分派器
事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
文件事件处理器 采用 IO 多路复用机制 同时监听多个 socket,根据 socket 上的事件来选择对应的事件处理器进行处理。多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序 会监听多个 socket,会将 socket 产生的事件放入 队列 中排队,事件分派器 每次从队列中取出一个事件,把该事件交给对应的 事件处理器 进行处理。
来看 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
猜你喜欢
- 项目背景:在项目中包含两个定时任务,配置信息如下:1、@Scheduled(initialDelay = 1,fixedDelay=1000
- package com.abc.dao;import java.sql.Connection;import java.sql.DriverM
- 1. 首先新建一个shiroConfig shiro的配置类,代码如下:@Configurationpublic class SpringS
- 在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较
- 一、算法描述波雷费密码是一种对称式密码,是首种双字母取代的加密法。下面描述算法步骤:1、从1号二维码M05,提取明文信息和密文,M05格式:
- springboot项目启动,访问报404错误今天在做一个springboot项目的时候,是接着别人的项目写的,写完之后想做一下测试,于是就
- 使用Integer类型查询出现的问题mapper.xml :<select id="count" paramete
- 说道线程,肯定会想到使用 java.lang.Thread.java这个类那么创建线程也主要有2种方式第一种方式:public class
- 前言在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并 * 况下使用HashMap
- java获取系统路径字体、得到某个目录下的所有文件名、获取当前路径package com.liuxing.test;import java.
- 本文实例讲述了Android+SQLite数据库实现的生词记事本功能。分享给大家供大家参考,具体如下:主activity命名为Dict:代码
- 本文为大家分享了Android实现带动画效果的可点击展开TextView 制作代码,效果图: 收起(默认)效果:点击展开后的效果:源码: 布
- java 获取字节码文件的几种方法总结在本文中,以Person类为例,将分别演示获取该类字节码文件的三种方式,其具体思想及代码如下所示:pu
- 本文实例讲述了Android编程之消息机制。分享给大家供大家参考,具体如下:一、角色描述1.Looper: 一个线程可以产生一个Looper
- 日志输出是所有系统必备的,很多开发人员可能因为常常使用log4j而忽视了JDK logging模块,两者之间是否有联系?是怎样的联系?JDK
- 背景接上文《失踪人口回归,mybatis-plus 3.3.2 发布》[1] ,提供了一个非常实用的功能 「数据安全保护」 功能,不仅支持数
- synchronized 和 Reentrantlock多线程编程中,当代码需要同步时我们会用到锁。Java为我们提供了内置锁(synchr
- 1 什么是cookie浏览器与WEB服务器之间是使用HTTP协议进行通信的,当某个用户发出页面请求时,WEB服务器只是简单的进行响应,然后就
- 打开首页,明显看到链接是https打头,https和http的通信协议差别,在于https安全性更高:http和https的差别很明显,二者
- 易于理解版package com.zhebie.ternary;public class ternary { public static v