有人说,在6.0之前呢,Redis是单线程的,这么说其实也不太准确,为什么呢?

因为Redis在4.0之后,就引入了多线程,比如说除了处理用户命令的主线程之外,还会起异步的线程去做一些资源释放,清理脏数据,删除大key等工作。

这里我们说之前的Redis是单线程,主要是指原来处理用户命令的线程,是单线程的。那么我们先看看6.0之前的Redis的线程模型图:

image.png
这就是6.0之前的Redis处理用户命令的主线程的线程模型图,主要过程主要分为:

  1. 获取可读Socket;
  2. 读取Socket;
  3. 解析并执行命令;
  4. 将结果回写给Socket。

之前为什么会这样设计呢?

据作者自己的说法就是:其实Redis瓶颈往往不在CPU,所以没有必要弄多线程,它的瓶颈往往在内存和网络IO。

Reids 6.0的线程模型

那么问题来了,在现代互联网应用,对并发性要求越来越高的情况下,如何去解决内存和网络这两个痛点呢?

(1) 对于内存来说,我们可以通过增加内存大小的方式来缓解;

(2) 对于网络来说,Redis作者呢,想到了另外一个办法,就是通过修改Redis的线程模型来对网络IO瓶颈进行缓解。
好了,那么接下来,我们先来看看在6.0版本的Redis,它的线程模型是怎么样的呢?如下图:

image.png

那么这种方式,为什么可以缓解网络IO问题呢?
前面已经讲过,单线程模型下,在高并发情况下,Redis的主线程很多时候,都在进行Socket的读写操作,这块儿其实消耗了很多的CPU等待时间。

但是呢,现代处理CPU一般都是多核架构的CPU,但Redis之前又只能利用一个核,所以单线程的模型限制了Redis的性能发挥。

所以在多核CPU的机器中,我们可以采用多线程(1个主线程+IO线程组)的模式来运行Redis。这样就可以充分利用多核CPU的优势来让Redis的性能得到更好的发挥。

新的问题来了?那么是不是IO线程的数量越多越好呢?

在Redis的配置文件中,有这样两个参数:io-threads-do-reads和io-threads

io-threads-do-reads的默认值是no,也就是说默认情况下,Redis并不会开启多线程模型。如果我要使用Redis的多线程模型,可以将在redis.conf文件中将该值设置为true。

io-threads是用来配置IO线程组线程数。

通常情况下,官方的建议是:如果你的CPU是4核,IO线程组一般设置为2-3;如果你的CPU是8核,IO线程组一般设置为5-6。

为什么官方会这样的去建议呢?那是因为如果IO线程设置太多,那在高并发的情况下,线程的上下文切换会成为新的瓶颈。