关于 Redis 为什么这么快,除了之前提到的,数据存储在内存、底层数据结构高效以外,还有什么其他原因呢?
我们都知道,Redis 是单线程高性能的。但是为什么 Redis 在单线程的情况下,还能做到高性能呢? 为什么不使用多线程呢? 多线程不是更快吗?
首先,需要说明,Redis 单线程的意思是说,Redis 处理外部的键值对操作请求是单线程的,指的是Redis 的网络IO和键值对读写是由一个线程完成的。 但是 Redis 其他保持高性能的功能,比如持久化、集群数据同步等,是由额外的线程处理的。
Redis 为啥使用单线程?
正如上文提到的那样,Redis 为什么不使用多线程?多线程的效率不是更高吗?
实际上,多线程的效率提升,并不是随着线程数的增加成比例增长的。其关键的瓶颈就在于,当面临多线程访问共享资源时,会产生资源的竞争与等待。 比如,当有多个请求同时访问某个 key 时,就可能产生资源竞争。 一言蔽之,就是多线程需要合理的机制来解决共享资源的并发访问控制问题。
Redis 为什么使用单线程还能这么快
实际上,Redis 采用了多路复用机制,来保证其处理网络IO大并发量请求操作时,能实现高吞吐量。
首先,我们需要知道,Redis 的单线程都处理了什么操作:
image.png
如上图所示,就是接受请求,操作请求,响应请求。
其中,在网络的IO处理中,可能导致的阻塞点在于 accept() 和 recv()。当 Redis 监听到连接请求,但是一直未能成功建立起连接时,会阻塞在 accept(),导致 Redis 无法和其他客户端建立连接。同样,当 Redis 通过 recv() 从客户端读取数据时,如果数据一直没有达到,同样会阻塞在 recv()。
基于多路复用的高性能IO模型
当监听到有请求发起连接时,Redis 会让内核监听这些套接字FD,一旦检测到FD上有请求到达时,会触发相应的回调函数,触发相应的事件。此时,Redis 线程就不会阻塞在某一个监听或者已连接套接字上。
通过回调函数触发了相应的事件后,这些事件会被放在一个事件队列中,Redis 单线程在对这个事件队列不断进行处理。
但是,在基于了多路复用的IO模型下,其单线程的阻塞点依然是有的。主要就阻塞在每次只能从事件队列中拿出一个事件进行处理。当这个事件处理的耗时特别长时,后面的事件都需要等待。
网友评论