《Redis设计与实现》读书笔记(十六) ——Redis文件事件 (原创内容,转载请注明来源,谢谢)

《Redis设计与实现》读书笔记(十六) ——Redis文件事件

(原创内容,转载请注明来源,谢谢)

一、概述

redis服务器是一个事件驱动程序,服务器需要处理以下两类事件:

1)文件事件(fileevent),redis服务器与客户端通过socket连接,文件事件是对socket的抽象,服务器与客户端通信会产生文件事件,服务器通过监听文件事件产生一系列操作。

2)时间事件(timeevent),redis的部分操作需要定时执行,主要是serverCron函数,例如定时清理过期键、定时aof写入等,时间事件是服务器对此类的抽象。

二、文件事件

1、reactor模式

redis基于reactor模式开发网络事件处理器,将其称之为文件时间处理器。该处理器通过I/O多路复用,同时监听多个socket,并根据socket当前处理的任务来关联不同的事件处理器。

reactor模式如下图所示:

其是处理并发I/O比较常见的一种模式,用于同步I/O。中心思想是将所有要处理的I/O事件注册到一个中心I/O多路复用器上,同时主线程阻塞在多路复用器上。一旦有I/O事件到来或是准备就绪(区别在于多路复用器是边沿触发还是水平触发),多路复用器返回并将相应I/O事件分发到对应的处理器中。

reactor中文称为反应器,即其不是等套接字来调用,而是提前建立好,并主动去调用到来或就绪的套接字。

当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作,会产生相应的文件事件。此时,文件事件处理器(即reactor)会调用之前关联好的处理器来处理事件。

I/O多路复用的reactor模式,使得redis虽然是单线程处理,但是仍然具有高效率。

2、文件事件处理器的构成

文件事件处理器由四部分组成——套接字、I/O多路复用程序、文件事件分派器、事件处理器,如下图所示:

通常,一个服务器需要同时处理多个套接字,因此文件事件可能并发出现。I/O多路复用程序是通过监听多个套接字,并将准备好的套接字按准备好的时间顺序转发给文件时间分派器。由文件时间分派器根据具体的事件类型,分派给不同的事件处理器。

I/O多路复用程序将并发出现的多个套接字加入到队列中,以有序、同步、每次一个的方式,将事件发送给文件事件分派器,并且当事件处理完毕后,才会将下一个事件发送过去。如下图所示:

I/O多路复用程序会监听多个套接字的读(ae.h/AE_READABLE)和写事件(ae.h/AE_WRITEABLE),当套接字可读或有新的可应答的套接字出现,产生读事件;当套接字可写,产生写事件。如果同时可读可写,则会先读再写。如果没有任何事件,返回的是ae.h/AE_NONE。

3、I/O多路复用程序

redis的I/O多路复用程序是通过包装操作系统原生的如select、epoll、evport、kqueue等I/O多路复用函数库,来实现I/O多路复用。由于redis底层对每种I/O多路复用都实现了相同的api接口,因此可以根据实际情况互换。每种复用方式,在redis里面是分别保存在一个.c的文件内。

1)select

select是较早的unix多路复用方式,其提供三种流——读、写、异常,调用时需要传入感兴趣的流,select将其拷贝到内核。select会使程序阻塞,让后其轮询每个流,当某个监听的流有操作时,其调用相关函数,返回结果。

由于select会将传入的流修改,并且需要全量传入、全量返回,对于大量的请求下,效率较低。

2)epoll与kqueue

epoll是linux内核的,kqueue是BSD内核的,其原理基本一致。其是通过创建一个句柄,并注册事件函数。即其是提前将有可能的事件都先注册好,当具体事件发生时去调用,而不是select的每次发生时在注册。

4、文件事件处理器

redis针对不同的文件事件,编写了多个文件事件处理器,包括处理各个客户端连接的应答处理器、接收客户端请求的命令请求处理器、向客户端返回命令结果的命令回复处理器、主从复制情况下的复制处理器。

1)应答处理器

名称是networking.c/acceptTcpHandler,用于对连接服务器监听套接字的客户端进行应答。redis初始化的时候,会将此应答处理器和套接字的读事件联系起来。当客户端发送连接请求,就会产生读事件(AE_READABLE)。

2)命令请求处理器

名称是networking.c/readQueryFromClient,用于处理读入客户端发送过来的套接字,当应答处理器连接到套接字的时候,命令请求处理器就会将读事件与其关联起来。当客户端发送请求时,就会产生读事件,命令请求处理器读入套接字中客户端发送的命令事件。

3)命令回复处理器

名称是networking.c/sendReplyToClient,用于将服务器执行命令后得到的回复返回给客户端。当有命令要返回给客户端,redis会将写事件与命令回复处理器关联起来,当客户端准备好接受服务器的回复,就会产生写事件,引发命令处理器将相关要返回给客户端的实际写入套接字。命令发送完毕后,会解除写事件和该客户端的关联。

4)示例

下面讲述一次完整的客户端与服务器连接事件。

当redis服务器正常运作时,监听套接字的事件AE_READABLE处于监听状态,且相应处理该事件的是应答处理器。

当有客户端向redis服务器发送连接请求,会产生AE_READABLE,触发应答处理器执行。处理器会进行连接并回复客户端,并创建客户端套接字,将套接字的AE_READABLE与命令请求处理器关联。

当客户端向redis服务器发送命令,会产生AE_READABLE事件,命令请求处理器会读入套接字中的命令,并传给相关执行程序去执行。

redis服务器执行完毕命令后,将产生相应的回复,服务器会将套接字的AE_WRITEABLE与命令回复处理器关联,当客户端尝试读取回复,客户端套接字将产生AE_WRITEABLE,命令回复处理器将执行,把要返回的内容写入套接字。

整个过程如下图:

——written by linhxx 2017.09.06

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-09-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码农分享

.net framework 3.5 安装失败解决方案

出错提示:windows功能无法安装以下功能:.NET Framework 3.5(包括.NET 2.0和3.0)

6.8K1
来自专栏Spark学习技巧

高性能:MYSQL异步客户端

实时处理领域,当需要使用外部存储数据染色的时候,需要慎重对待,不能让与外部系统之间的交互延迟对流的整个进度取决定性的影响。

4382
来自专栏老秦求学

汇编语言学习之汇编语言源程序的输入

  在dos下输入汇编源程序的方法   一 环境的搭建   windows下运行“windows+r”键入“cmd”,就就进入dos系统,输入“debug”进入...

3475
来自专栏极客猴

Django 实战2:利用 Session 实现自动登录机制

上篇文章中讲到 Django 如何启动以及配置 sessions 功能。sessions 功能用是跟踪用户的状态,经常结合 Cookie 功能实现自动登录功能。...

2343
来自专栏决胜机器学习

PHP网络技术(一)——HTTP协议

PHP网络技术(一)——HTTP协议 (原创内容,转载请注明来源,谢谢) 一、概述 HTTP协议是一个基于应用层的通信规范,通信双方都遵守此协...

4226
来自专栏iOSDevLog

iOS打包framework - Swift完整项目打包Framework,嵌入OC项目使用

--------------------------------打包篇-------------------------------****

1854
来自专栏武培轩的专栏

HTTP 0.9 HTTP 1.0 HTTP 1.1 HTTP 2.0区别

HTTP协议 :Hyper Text Transfer Protocol(超文本传输协议),是用于从万维网(WWW:World Wide Web)服务器传输超文...

3215
来自专栏依乐祝

Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据

本来这篇文章在昨天晚上就能发布的,悲剧的是写了两三千字的文章居然没保存,结果我懵逼了。今天重新来写这篇文章。今天我们就一起来探讨下如何重写Ocelot配置文件的...

982
来自专栏Albert陈凯

HTTP、TCP、UDP:通信协议的规则和区别

TCP、HTTP、UDP:都是通信协议,也就是通信时所遵守的规则,只有双方按照这个规则“说话”,对方才能理解或为之服务。 TCP HTTP UDP三者的...

3158
来自专栏云知识学习

关于FTP搭建问题

1. 匿名服务器的连接(独立的服务器) 在/etc/vsftpd.conf(或在/etc/vsftpd/vsftpd.conf)配置文件中添加如下几项: A...

71910

扫码关注云+社区

领取腾讯云代金券