1. 官网的解释


CPU并不是您使用Redis的瓶颈,因为通常Redis要么受内存限制,要么受网络限制。例如,使用在一般Linux系统上运行的流水线Redis每秒可以发送一百万个请求,因此,如果您的应用程序主要使用O(N)或O(log(N))命令,则几乎不会使用过多的CPU 。
但是,为了最大程度地利用CPU,您可以在同一服务器上启动多个Redis实例,并将它们视为不同的服务器。在某个时候,单个实例可能还不够,因此,如果您要使用多个CPU,则可以开始考虑更早地分片的某种方法。
但是,在Redis 4.0中,我们开始使Redis具有更多线程。目前,这仅限于在后台删除对象,以及阻止通过Redis模块实现的命令。对于将来的版本,计划是使Redis越来越线程化。

2. Redis为什么是单线程的?

Redis是基于内存操作的,CPU并不是Redis的瓶颈,Redis的瓶颈是机器的内存网络带宽,既然可以使用单线程来实现,那当然就使用单线程了。

相反,如果使用多线程的话,多个CPU还要进行上下文切换,CPU上下文切换的效率远远比不上直接在内存中读取的速度;并且,采用多线程,还会带来数据安全的问题,假如我们在操作redis的List、Hash等数据结构时,多线程就可能存在数据不安全的情况,这时候就需要加锁,一旦加锁就又影响了程序的执行速度。

3. Redis单线程的优势和劣势

优势

  1. 代码更清晰,处理逻辑更简单;
  2. 不用去考虑各种锁的问题,不存在加锁、释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  3. 不存在“多进程或者多线程导致的切换”而消耗CPU。

劣势

  1. 无法发挥多核CPU性能(可以通过在单机开多个Redis实例来完善,单一线程只能用到一个CPU核心,所以可以在同一个多核的服务器中,启动多个实例,组成master-master或者master-slave的形式,耗时的读命令可以完全在 slave 进行,充分发挥 Redis 的作用)。

4. Redis速度为什么那么快?

  1. Redis是纯内存数据库,避免大量访问数据库,减少直接读取磁盘数据,redis将数据储存在内存里面,读写数据的时候都不会受到硬盘 I/O 速度的限制;
  2. Redis使用单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件,减少了线程切换时上下文的切换和竞争,也不存在多进程或者多线程导致的切换而消耗CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  3. Redis采用自己实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。
  4. Redis采用了非阻塞I/O多路复用机制

5. Redis的多路IO复用

redis 采用网络IO多路复用技术,来保证在多连接的时候系统的高吞吐量。
多路指的是多个socket网络连接,复用指的是复用一个线程。

多路复用主要有三种技术:select,poll,epoll(epoll是最新的、也是目前最好的多路复用技术),可以同时监察多个流的 I/O 事件,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流,并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作,从而提高效率。

采用多路I/O复用技术的原因:

  1. 可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗);
  2. Redis在内存中操作数据的速度非常快(内存里的操作不会成为这里的性能瓶颈)。

主要以上两点造就了Redis具有很高的吞吐量。

6. Redis的持久化

由于redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,于是需要开启redis的持久化功能,将数据保存到磁盘上,当redis重启后,可以从磁盘中恢复数据。

redis提供两种方式进行持久化,一种是RDB持久化(原理是将redis在内存中的数据库记录定时 dump到磁盘上的RDB持久化),另外一种是AOF(append only file)持久化(原理是将redis的操作日志以追加的方式写入文件)。

持久化似乎和redis的速度并没有直接关系,但是这保证的redis数据的安全性和可靠性,也起到数据备份的作用。