深度解析Redis线程模型设计原理

全是干货的技术号:
本文已收录在github,欢迎 star/fork:
https://github.com/Wasabi1234/Java-Interview-Tutorial

1 单线程模型设计

image

单线程模型为何效率高

  • 纯内存操作
  • 基于非阻塞的IO多路复用机制
  • 避免了多线程的频繁上下文切换

2 文件事件处理器

Redis 基于 Reactor 模式开发了自己的网络事件处理器 - 文件事件处理器(file event handler,后文简称为 FEH),而该处理器又是单线程的,所以redis设计为单线程模型。

  • 采用I/O多路复用同时监听多个socket,根据socket当前执行的事件来为 socket 选择对应的事件处理器。
  • 当被监听的socket准备好执行acceptreadwriteclose等操作时,和操作对应的文件事件就会产生,这时FEH就会调用socket之前关联好的事件处理器来处理对应事件。

所以虽然FEH是单线程运行,但通过I/O多路复用监听多个socket,不仅实现高性能的网络通信模型,又能和 Redis 服务器中其它同样单线程运行的模块交互,保证了Redis内部单线程模型的简洁设计。

  • 下面讲讲文件事件处理器的几个组成部分。


    image

2.1 socket

文件事件就是对socket操作的抽象, 每当一个 socket 准备好执行连接accept、read、write、close等操作时, 就会产生一个文件事件。 一个服务器通常会连接多个socket, 多个socket可能并发产生不同操作,每个操作对应不同文件事件。

2.2 I/O多路复用程序

I/O 多路复用程序会负责监听多个socket。

尽管文件事件可能并发出现, 但 I/O 多路复用程序会将所有产生事件的socket放入队列, 通过该队列以有序、同步且每次一个socket的方式向文件事件分派器传送socket。
当上一个socket产生的事件被对应事件处理器执行完后, I/O 多路复用程序才会向文件事件分派器传送下个socket, 如下:


image

I/O多路复用程序的实现

Redis 的 I/O 多路复用程序的所有功能都是通过包装常见的 select 、 epoll 、 evport 和 kqueue 这些 I/O 多路复用函数库实现的。
每个 I/O 多路复用函数库在 Redis 源码中都对应一个单独的文件:
[图片上传失败...(image-c54286-1598968387613)]

因为 Redis 为每个 I/O 多路复用函数库都实现了相同的 API , 所以 I/O 多路复用程序的底层实现是可以互换的。Redis 在 I/O 多路复用程序的实现源码ae.c文件中宏定义了相应规则,使得程序在编译时自动选择系统中性能最高的 I/O 多路复用函数库作为 Redis 的 I/O 多路复用程序的底层实现:性能降序排列。

image

2.3 文件事件分派器

文件事件分派器接收 I/O 多路复用程序传来的socket, 并根据socket产生的事件类型, 调用相应的事件处理器。

2.4 文件事件处理器

服务器会为执行不同任务的套接字关联不同的事件处理器, 这些处理器是一个个函数, 它们定义了某个事件发生时, 服务器应该执行的动作。

处理器映射

Redis 为各种文件事件需求编写了多个处理器,若客户端:

  • 连接Redis,对连接服务器的各个客户端进行应答,就需要将socket映射到连接应答处理器
  • 写数据到Redis,接收客户端传来的命令请求,就需要映射到命令请求处理器
  • 从Redis读数据,向客户端返回命令的执行结果,就需要映射到命令回复处理器

当主服务器和从服务器进行复制操作时, 主从服务器都需要映射到特别为复制功能编写的复制处理器。

2.5 文件事件的类型

I/O 多路复用程序可以监听多个socket的 ae.h/AE_READABLE 事件和 ae.h/AE_WRITABLE 事件, 这两类事件和套接字操作之间的对应关系如下:

  • 当socket可读(比如客户端对Redis执行write/close操作),或有新的可应答的socket出现时(即客户端对Redis执行connect操作),socket就会产生一个AE_READABLE事件
    [图片上传失败...(image-77efd2-1598968387613)]
  • 当socket可写时(比如客户端对Redis执行read操作),socket会产生一个AE_WRITABLE事件。
    [图片上传失败...(image-6ea1a3-1598968387613)]

I/O多路复用程序可以同时监听AE_REABLEAE_WRITABLE两种事件,要是一个socket同时产生这两种事件,那么文件事件分派器优先处理AE_REABLE事件。即一个socket又可读又可写时, Redis服务器先读后写socket。

3 总结

最后,让我们梳理一下客户端和Redis服务器通信的整个过程:


image
  1. Redis启动初始化时,将连接应答处理器AE_READABLE事件关联。
  2. 若一个客户端发起连接,会产生一个AE_READABLE事件,然后由连接应答处理器负责和客户端建立连接,创建客户端对应的socket,同时将这个socket的AE_READABLE事件和命令请求处理器关联,使得客户端可以向主服务器发送命令请求。
  3. 当客户端向Redis发请求时(不管读还是写请求),客户端socket都会产生一个AE_READABLE事件,触发命令请求处理器。处理器读取客户端的命令内容, 然后传给相关程序执行。
  4. 当Redis服务器准备好给客户端的响应数据后,会将socket的AE_WRITABLE事件和命令回复处理器关联,当客户端准备好读取响应数据时,会在socket产生一个AE_WRITABLE事件,由对应命令回复处理器处理,即将准备好的响应数据写入socket,供客户端读取。
  5. 命令回复处理器全部写完到 socket 后,就会删除该socket的AE_WRITABLE事件和命令回复处理器的映射。

参考

  • 《Redis 设计与实现》
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269