众所周知,redis是单线程的,但是我相信大部分学过redis的都有有这样的疑问?既然是单进程的,它的读写效率为什么那么高?
这里不能从单线程的效率出发来解释这事,当然单线程也有本身固有的好处,这里就必须说说进程,线程,以及协程的区别。
进程:在计算机被人来发明出来的时候,那时计算机的工作都是进程
线程:进程的子进程就是线程,线程是干活的,进程是指挥的。
协程:也是单线程的,只不是是程序控制调度而已,非系统调度
所有,后来就有人说,进程是最小的资源分配单位,线程是cpu调度的最小单位。
进程到线程,再到协程的发展,完全是因为当时的计算机大环境并不满足当时的情况下才发展起来的。
对比而言,进程占用的系统资源比较多,而且创建一个进程的代价比较大,而线程恰恰相反,每个进程可以创建成百上千个线程,线程占用的系统资源非常少,可以忽略不计,而且只有有需要,随时可以按需创建。但线程也有它自己的缺陷,比如在cpu不足的机器上创建了大量的线程,cpu调度就会紧张,导致每个线程刚刚分配一点cpu时间,正要被执行代码的时候,cpu时间到期了,此时cpu会切换其他等待cpu时间最长的进程来运行,没等进程工作呢?cpu又切换了。。。如此便会浪费大量的cpu时间都在做无用功的时间上,也就是cpu一直很忙,却没有一点效果。这也就是线程太多的情况下,比进程更槽糕,也就是程序为什么运行的效率会更慢。
进程的好处就是它的资源,无论是寄存器,内存等,都是独享的。没有竞争条件,而且线程不是这样的,它的部分资源是又它的父进程分配的,父进程创建的所有线程都会共享父亲的部分资源。并且在cpu切换的时候,线程会竞争,切换的过程中导致大量的上下文切换,也会消耗一部分时间,尤其是服务器资源紧张,并有大量线程切换的时候,服务器性能断崖式下降。
后来又出现了协程,协程也就是单线程,单线程有个优势,它节约了在多个cpu之间切换的时间损耗,效率上在特定场景下肯定要比多进程,多进程的场景下高很多,注意只是在特定场景下,而非所有情况。
那么redis采用单线程也是有这方面的原因的,但这只是一方面,光靠它是单线程而使redis的读并发十几万,写并发2w+是站不住脚的。
redis快的原因总结:
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;
5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
以上几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:
多路 I/O 复用模型
多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。
欢迎长按下图关注公众号小璇坨坨
十年IT积累倾囊相授




