文章目录
- redis为什么不用多线程?
- 为什么单线程Redis还这么快?
- 并非真正的单线程
- IO多路复用
- 纯内存访问
- 高效的数据结构
- 那单线程有哪些性能问题呢?
redis为什么不用多线程?
主要是两个原因:
- 没必要
Redis Server本身可能出现的性能瓶颈点无非就是网络IO、CPU、内存。但是CPU不是Redis的瓶颈点,所以没必要使用多线程来执行指令。 - 多线程副作用大
如果采用多线程,意味着对于redis的所有指令操作,都必须要考虑到线程安全问题,也就是说需要加锁来解决,这种方式带来的性能影响反而更大。
为什么单线程Redis还这么快?
并不是真正的单线程,很多地方也用到了子进程来加快速度
io多路复用、内存访问、高效的数据结构等等优化进一步加速。
并非真正的单线程
Redis的网络IO和键值对读写是由一个线程来完成的,但Redis的其他功能,比如持久化、异步删除、集群数据同步
等,其实是由额外的线程
执行的。
所以严格来说,Redis并不是单线程,只是网络IO和键值对读写
占主要,所以我们才不严谨
的把Redis称为单线程而已。
IO多路复用
纯内存访问
高效的数据结构
那单线程有哪些性能问题呢?
Redis单线程处理IO请求性能瓶颈主要包括2个方面:
1、任意一个请求在server中一旦发生耗时
,后面的请求都要等前面这个耗时请求处理完成,自己才能被处理到。耗时的操作包括以下几种:
- 操作bigkey
写入、删除 一个bigkey在分配内存时需要消耗大量的时间 - 使用复杂度过高的命令
例如SORT/SUNION/ZUNIONSTORE
,或者O(N)命令,但是N很大 - 大量key集中过期
Redis的过期机制也是在主线程中执行的,大量key集中过期会导致处理一个请求时,大量时间花在了删除过期key
。
解决:Redis在4.0推出了lazy-free
机制,把bigkey释放内存的耗时操作放在了异步线程
中执行,降低对主线程的影响。 - 淘汰策略
淘汰策略也是在主线程执行的,当内存超过Redis内存上限后,每次写入都需要淘汰一些key,也会造成耗时变长; - AOF刷盘开启
always
机制
每次写入都需要把这个操作刷到磁盘,写磁盘的速度远比写内存慢,会拖慢Redis的性能; - 主从
全量同步
生成RDB
虽然采用fork子进程生成数据快照,但fork这一瞬间也是会阻塞整个线程的,实例越大,阻塞时间越久;
2、并发量非常大时,单线程读写客户端IO数据存在性能瓶颈,虽然采用IO多路复用机制,但是读写客户端数据依旧是同步IO
,只能单线程依次读取客户端的数据,无法利用到CPU多核。