说Redis是单线程其实不严谨
Redis到底是不是单线程
Redis并不是一个单线程程序,不信的话你执行如下命令运行看一下。
top -Hp `pidof redis-server`
这你能简单地不加任何修饰地说它是单线程?这明明是多线程。
那为什么网上都说是单线程,其实我说那都不严谨。
说redis是单线程,其本意是指redis处理cmd的操作,都是在一个线程内进行的,而不是多线程处理cmd。
在现在最新的版本里,redis的网络IO线程已经是多线程了。
为什么redis不使用多线程处理cmd?
两个方面的原因:
1、加锁会很复杂,锁的粒度不好控制。redis支持多种对象类型,且每种对象类型可以使用多种数据结构来实现,这会导致锁的使用异常繁琐。
2、频繁的CPU切换,抵消了多线程带来的优势。但其实这个点,我觉得有点牵强,因为可以把线程绑定到特定的CPU核上,就像nginx做的那样。
主要原因,我觉得还是加锁带来的复杂度和性能损耗。
难道单线程操作cmd就没有坏处吗?有什么局限?
单线程操作cmd的局限就是不能有耗时的操作,不能有阻塞。
为什么单线程这么快?本质是什么?做了什么优化?
1、都是内存操作
2、数据结构很高效
3、采用了高效的reactor模型,不会引起阻塞。
4、耗时阻塞的操作,另起线程处理。比如关闭大文件、刷盘、IO线程解码等都是另起的单独的线程。
5、对象类型选择了不同的数据结构实现。比如hash对象,节点数小于512时使用ziplist,大于512时使用dict。
ziplist数据结构对内存的使用比较紧凑,比较省内存(比较redis是内存数据库),但因其是连续的内存块,节点数较多时,线性就比较耗时,但单线程不能有耗时的操作,所以节点数多的时候,redis就换成字典,字典比较占空间,但是查找就比较高效,也就是空间换时间。所以一种对象在不同场景下会使用不同的数据结构。
6、分治的思想。
将阻塞的大的操作,拆分成小的操作。比如rehash的时候。
为什么reactor模型这么高效,本质是什么?
1、IO多路复用。可以同时监测多条连接的IO事件。
2、采用非阻塞IO。read/write不会阻塞。