Redis是单线程的为什么如此快
①redis是基于内存的
首先,Redis 是基于内存的数据库,不论读写操作都是在内存上完成的,完全吊打磁盘数据库的速度。
②Redis是单线程模型,从而避开了多线程中上下文频繁切换的操作
Redis 的单线程指的是 Redis 的网络 IO 以及键值对指令读写是由一个线程来执行的。
③使用多路I/O复用模型,非阻塞I/O
④c语言实现,距离操作系统较近,执行速度更快
redis的线程模型
redis的线程模型也可以解释其为什么如此快,里面有IO多路复用程序可以同时监听多个socket,相对于里面是多线程了,可以支持并发操作,并由文件事件分派器分派事件。
redis内部使用文件事件处理器,这个事件处理器是单线程的,所以redis才叫做单线程的模型。他采用IO多路复用机制同时监听多个socket,将事件的socket压入到内存序列中,然后由文件事件分派器根据socket上面的事件类型来选择对应的事件处理器来处理。
文件事件处理器的结构:
-
多个socket
-
IO多路复用程序
-
文件事件分派器
-
事件处理器(连接应答处理器、命令请求处理器、命令恢复处理器)
多个socket可能会并发产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用会监听多个socket,将产生事件的socket放入队列排队,事件处理器每次从队列中取出有个socket,根据socket的事件类型交给对应的事件处理器进行处理。
下面是客户端与redis的一次通信过程
通信是通过socket来完成的。
-
首先,redis服务端进行初始化的时候,会将server socket的AE_READABLE事件与连接应答处理器关联
-
客户端socket01向redis进行的server socket请求建立连接,此时server socket会产生一个AE_READBLE事件,IO多路复用程序监听到server socket产生的事件后,将socket压入队列中,文件事件分派器从队列中获取socket,交给连接应答处理器,连接应答处理器会创建一个能与客户端通信的socket01,并将socket01的AE_READABLE事件与命令请求处理器关联
-
假设此时客户端发送了一个set key value请求,此时redis的socket01会产生AE_READABLE事件,IO多路复用程序将socket01压入队列,此时事件分派器从队列中获取到socket01产生的AE_READABLE事件。由于前面的socket01的AE_READABLE事件已经与命令请求处理器关联,因此事件分派器将事件交给命令请求处理器处理,命令请求处理器读取socket01的key value并在自己内存中完成key value的设置。操作完成后,他会将socket01的AE WRITABLE事件与命令回复处理器关联。
-
如果此时客户端准备好接受返回结果,那么redis的socket01会产生一个AE_WRITABLE事件,同样压入队列中,事件分派器找到相关联的命令回复处理器,由命令回复处理器对socket01输入本次操作的一个结果,比如ok,之后就解除socket01与AE_WRITABLE事件与命令回复处理器的关联。