如果在网上查过“Redis为什么快”这个问题的同学,一定看到过其中一个原因:Redis采用了单线程模型,减少了线程的上下文切换和竞争。然后又使用了I/O多路复用模型,关于I/O多路复用,可以看下这篇文章:I/O多路复用。epoll的时间复杂度是O(1),的确并发不是问题,但是为什么最新发布的Redis6.0里,竟然支持了多线程呢?
请注意!!I/O多路复用的epoll,解决的是并发问题,并发,而不是并行。
Redis是靠着基于内存,处理效率高来规避并行问题的,这就像是一个高效的程序员,产品无论给他什么需求,他都能在1天内干完;然后I/O多路复用就像是一个很棒开发流程中的项目经理,只要你干完我就能立刻给你安排好下一份工作,一点不会耽误时间,于是乎两人搭配,一点都不会阻塞住,就算产品一天提了3个需求(并发),那3天后也全部交付了;于是乎也用不到别的程序员了,这位大哥一个人就能搞定了(单线程),也用不着和其他程序员沟通(上下文切换),更是省时省力。但是终于有一天,产品经理终搞出了一个非常难搞的需求,这个需求,需要15人日才能做完,但是其他工作,依然在不断产生,这下就算其他需求花不了多长时间,也只能排到15天以后了,这样看起来,一个人的问题就来了,他不能分身(并行)。所以,Redis的生产环境一般是禁用keys这种命令的,因为一个不能很快结束的命令会阻塞其他的请求。
Redis的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程。之所以这么设计是不想 Redis 因为多线程而变得复杂,需要去控制 key、lua、事务,LPUSH/LPOP 等等的并发问题。Redis 在最新的几个版本中加入了一些可以被其他线程异步处理的删除操作,也就是我们在上面提到的 UNLINK、FLUSHALL ASYNC 和 FLUSHDB ASYNC,我们为什么会需要这些删除操作,而它们为什么需要通过多线程的方式异步处理?
我们知道Redis可以使用del命令删除一个元素,如果这个元素非常大,可能占据了几十兆或者是几百兆,那么在短时间内是不能完成的,这样一来就需要多线程的异步支持。
而上面提到的keys命令是需要同步返回的,所以即使在Redis6.0,这个命令应该在生产环境依然会被禁用。