Redis 它是单线程还是多线程,你认为它是单线程还是多线程?
不管你回答是单还是多都是错误的。为什么?来!为什么?跟我来。Redis为什么到底是单线程的多线程呢?其实呢从 Redis这个版本的变化,它的单线程就者多线程也发生了変化。
单线程
比方说 Redis的版本,Redis5以及5之前的所有版本它部是单线程。这个单线程并不是 Redis是内部它只有一个线程,指的是 Redis它的 work线程,工作线程是单线程。
那么它的工作机制是怎么处理的呢,我觉得面试官问你是单还是问你是多线程,他其实希望得到答案是,你能够能够从它的工作机制角度来描述它的单或者多的优点以及缺点。
ok!我们先看一下早期的版本。Redis5.X 版本以及他之前的版本单线程的工作机制。
比方说,咱们这个地方有两个客户端:Client1、Client2。可以是 Java客户端也可以是其他客户端。然后我们客户端这边是我们的 Redis,这个线程叫做 Redis 单 worker线程,干活线程。
这两个客户端连接到我的 Redis之后,他会发送指令。
Client 1 发送指令
比方说 Client1发了一个set name taopanfeng指令到 Redis。然后呢,紧接着 Client2也发了指令叫 get age这种命令到我们 Redis i,那么大家知道我们的 Redis它是一个单 worker 线程,如果说要处理这两个指令的话,肯定是有一个顺序的,是以这种串行的方式来执行的。
顺序谁先发过来先执行谁,比方说 Client1先发过来。发过来之后,Redis 当前这个单 worker线程要执行这组指令的前提什么?前提是要把这个指令,这个io流先读到,读到这个io流。
读到之后第二步对于我们接收到的这个io流,因为它是tcp的协议,所以是流的方式,它会把这组指令进行计算,说白了计算就是把这个数据插到 Redis的内存中。
计算完之后,我们要把这个数据计算的结果往回写叫 write,也就是 write io。
这个数据插到 Redis的内存中,到底我插入成功还是失败,我会把这个结果告诉我们客户端。就跟往数据库里插入条数据,插入成功了还是没插入成功它会告诉你(effect n rows)影响一行,还是影响两行,影响的行数。
ok。这是咱们单线程的情况下,当前第一个客户端发过来的一条数据要进行执行,我们 Redis 单 worker线程要做这部分事情。
Client 2 发送指令
同时呢,Client2 也发过来数据了,发过来数据怎么办呢?
第一步,我们只有ー个哥们在干活 他要执行这个指令,前提是什么,先把这个指会拿到
第一步,先把这个指令给他读到,也就是 read io,还有把这个数据流读到之后计算,进行查询,查询完之后返回结果,进行write io,当前这个 get age它到 Redis的内存中查的数据多少,返回给 Client2。
所以,看到没有,我们的单 workers线程,Redis 是5.x以及之前的版本,它的处理机制是一个哥们处理了这六个事情,其实就是为了执行这两个指令。
多线程
那么只到 Redis 6.0版本之后,它有了这个多线程的概念。
ok!我们同样的以这个例子来讲,比方说我们现在有两个客户端 Client1、Client2 要发送指令,请注意看我们的 Redis 6.0后,它的 worker线程还是一个单线程,同样的单 worker线程,还是个单 worker 线程。
Client 1 发送指令
比方说 现在呢,我们这个 Client1发过来一条指令:set name taopanfeng,发过来之后,很明显,第一步我们要去读 这个IO,假如我们有个客户端发过的数据了,之前读是由单 worker线程读的,对吧。
现在假如我们发现 Client1发过来数据的话,Redis服务端会新开辟一个 IO子线程,这个时候就有多线程的概念了。
IO子线程专门来读取我们的第一个指令 read,之前读是用的 worker读,现在的 IO子线程读。
读完之后计算,计算由我们的单 worker线程计算,在第二个时间轴进行计算,计算完之后,要把计算的结果返回到这个客户端,又是由我们的 IO子线程进行返回。这就是我们当前 Client1连过来。多线程。
Client 2 发送指令
假如这个时候我们还有个连接,还有客户端也发了一个命令过来,那么它还会开辟另外一个线程,当然这个线程是可以复用的也叫 IO子线程。
第一步,他发过来,这个比方说叫get age,我们第一步还是读read,读完之后要计算,第二个指令很明显,第二指令要计算的话,单 worker 线程它只能串行的执行,应该在我们的第一个指令的后面。它不能同时执行,因为只有ー个哥们,对吧,虽然在第一个指令后面进行计算,计算完之后怎么办,在后面这个时间维度计算对吧,然后要返回结果 write 由我们自己对应的另外一个 IO子线程返回结果给 Client2。
总结
所以,我们之前 redis 5.x以及 redis 4.x、 redis 3.x这种单 worker 线程它要执行两个指令。它是有几个时间维度?123456,6个对吧。
现在 redis 6.0版本之后它是多线程,要执行同样的两个指令,需要几个时间维度,1234,4个时间维度。
4个时间维度,和 6个时间维度,大家想想哪个时间更短?哪个时间更快?
是不是下面的多线程时间更快,也就说性能更高。
这就是为什么 redis在6.0版本之后它要推出多线程概念。
你看懂了吗?你真的看懂了吗?
