Redis线程模型消息处理进程I/O复用器实现文件事件类型文件事件处理器连接响应处理器命令请求处理器命令响应处理器为什么Redis是单线程Redis快
线程模型
Redis基于Reactor模式开发了自己的网络事件处理器。 该处理器被称为http://www.Sina.com/(文件事件处理程序)
文件处理器使用文件事件处理器,访问I/O 多路复用(multiplexing)程序
套接字相关(动词)根据套接字当前正在执行的任务而不同的监听 多个套接字-Socket
消息处理流程在套接字-套接字准备执行连接响应(accept )、读取(read )、写入(right )、关闭(close ) )等操作时,发生与操作对应的文件事件
此时,3358www.Sina.com/或事件处理器套接字-套接字-套接字之前相关联的3358www.Sina.com/为http://www.Sina.com
虽然可能同时发生多个文件事件,但文件事件处理器始终有调用事件发生的3358www.Sina.com/在一个队列中
然后,通过该队列,有序地(sequentially )、同步地(synchronously ),对每个套接字以套接字-Socket方式向文件事件调度器传输套接字
I/O复用器在处理了在前一个套接字-套接字中生成的事件之后,由与该事件相关联的事件处理器执行该套接字-套接字,然后在事件处理器中发送下一个套接字
I/O多路复用器实现“多路复用”是指多个网络连接
“复用”是指复用同一线程
复用I/O复用技术使单个线程能够高效地处理多个连接请求。 可以将网络I/O的时间消耗降到最低
Redis在内存中操作数据的速度非常快,这意味着内存中的操作不会成为影响Redis性能的瓶颈
redis I/O复用程序的所有功能都是通过包装I/o复用函数库实现的,如选择、轮询、ev端口和kqueue
每个I/O复用库都对应于Redis源代码中的一个单独文件
因为Redis为每个I/O复用库实现了相同的API,所以I/O复用程序的基本实现是兼容的
Redis在I/O多路复用器的实现源代码中用#include宏定义了适当的规则
程序在编译时自动选择系统中性能最高的I/O复用函数库作为redis I/o复用程序的基础
文件类型I/O复用器可以接收多个套接字的ae.h/AE_READABLE和ae.h/AE_WRITABLE事件
这些事件与套接字操作的对应关系如下。
套接字变为可读时(客户端可以对套接字执行write操作, 执行close操作)或新的响应)套接字出现时)客户端对服务器的监听套接字执行connect操作)套接字生成AE_READABLE事件对套接字可写入时) 套接字生成的AE_WRITABLE事件I/O复用器允许服务器同时接收套接字的AE_READABLE和AE_WRITABLE事件
如果套接字同时生成这两个事件,则文件事件调度程序将优先处理AE_READABLE事件,并且在处理AE_READABLE事件之前不会处理AE_WRITABLE事件
也就是说,如果套接字是可读和可写的,则服务首先读取套接字,然后写入套接字
文件事件处理器Redis为文件事件创建了多个处理器。 这些处理器分别用于满足不同的网络通信要求。 典型的处理器包括:
连接应答处理器为了应答与服务器连接的各客户端,服务器为了接收插座相关命令而与处理器命令要求处理器连接,为了接收来自客户端的命令要求,服务器针对客户端插座相关命令,对处理器命令应答处理器为了向客户机返回指令的执行结果,服务器将应答处理器连接到客户机套接字相关指令应答处理器的networking.c中的acceptTcpHandler函数是Redis的连接应答处理器
该处理器用于对接收连接到(动词)服务器)的套接字的客户端进行应答,具体实现为sys/socket.h/accept函数的包装
初始化Redis服务器后,程序将响应处理器和服务器接收套接字AE_R的连接
EADABLE事件关联起来当有客户端用sys/socket.h/connect函数 连接(动词) 服务器(的)监听套接字的时候, 套接字就会产生AE_READABLE 事件, 引发连接应答处理器执行, 并执行相应的套接字应答操作 命令请求处理器
networking.c中readQueryFromClient函数 是 Redis的命令请求处理器
这个处理器 负责 从套接字中 读入 客户端 发送的命令请求内容, 具体实现为unistd.h/read函数的包装
当一个客户端通过 连接应答处理器 成功连接到 服务器之后,
服务器 会 将客户端套接字的AE_READABLE事件 和 命令请求处理器关联起来
当客户端向服务器发送命令请求的时候,套接字 就会产生 AE_READABLE事件,引发命令请求处理器执行,并执行相应的套接字读入操作
在客户端连接服务器的整个过程中,服务器 都会 一直为 客户端套接字的AE_READABLE事件 关联 命令请求处理器
networking.c中sendReplyToClient函数 是 Redis的命令回复处理器
这个处理器 负责 将服务器执行命令后得到的命令回复 通过 套接字 返回 给客户端,具体实现为unistd.h/write函数的包装
当服务器有命令回复 需要传送给 客户端的时候,服务器 会将 客户端套接字的AE_WRITABLE事件 和 命令回复处理器 关联起来
当客户端 准备好 接收服务器传回的命令回复时,就会产生AE_WRITABLE事件,引发命令回复处理器执行,并执行相应的套接字写入操作
当命令回复发送完毕之后, 服务器就会 解除 命令回复处理器 与 客户端套接字的 AE_WRITABLE 事件之间的关联
Redis的数据结构并不全是简单的Key-Value,还有list,hash等复杂的结构,这些结构有可能会进行很细粒度的操作,比如在很长的列表后面添加一个元素,在hash当中添加或者删除
一个对象
这些操作可能就需要加非常多的锁,导致的结果是同步开销大大增加
在单线程的情况下,就不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗单线程多进程集群方案
单线程的威力实际上非常强大,每核心效率也非常高,多线程自然是可以比单线程有更高的性能上限,但是在今天的计算环境中,即使是单机多线程的上限也往往不能满足需要了,需要进一步摸索的是多服务器集群化的方案,这些方案中多线程的技术照样是用不上的
所以单线程、多进程的集群不失为一个时髦的解决方案CPU消耗
采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU
但是如果CPU成为Redis瓶颈,或者不想让服务器其他CUP核闲置,可以怎么做?
可以考虑多起几个Redis进程,Redis是key-value数据库,不是关系数据库,数据之间没有约束
只要客户端分清哪些key放在哪个Redis进程上就可以了