Redis高性能IO模型
Redis是单线程,Redis的网络IO的键值对读写都是一个线程完成,也是对外提供键值存储主要流程。但Redis的其他功能,持久化、异步删除、集群数据同步都是由额外的现场执行,严格意义上来说Redis 并不是单线程。
Redis 单线程
多线程编程模式面临的共享资源的并发访问控制问题,为了避免这些问题Redis采用的单线程的模式,而且单线程降低Redis的内部实现。
Redis 单线程快的原因
- Redis 大部分操作都是在内存上完成的,并且有高效的数据结构
- Redis 采用IO多路复用,能保证在网络IO中可以并发处理客户端的请求,实现吞吐率
Redis单线程处理IO请求瓶颈主要包括两个方面:
- 任意一个请求在server中一旦发生耗时操作,都会影响到整个server的性能。就是当前耗时的请求会阻塞后面请求,等当前处理完后面才会处理。耗时操作包括:
- 操作bigkey: 写入bigkey在分配内存时需要消耗更多的手机,删除bigkey释放空间也同样耗时
- 使用复杂度过高的吗命令: 例如SORT/SUNION/ZUNIONSTORE,或者O(N)命令,但是N很大,例如lrange key 0 -1一次查询全量数据;
- 大量key集中过期: redis的过期机制也是在主线程执行的,大量key集中过期会导致处理一个请求时,都在删除过期key,耗时变长
- 淘汰策略: 淘汰策略也是在主线程执行的,当内存超Redis上限后,每次写入都会淘汰一些key,也会耗时较长
- AOF刷盘开启always机制:每次写入都需要把这个操作刷新到磁盘,写磁盘的操作比写内存慢,会拖慢Redis的性能
- 主从全量同步生成RDB: 虽虽然采用fork子进程数据快照,但是fork这一瞬间也会阻塞整个线程,实力越大阻塞越久
- 并发量非常大时,单线程读写客户端IO数据存在性能瓶颈。虽然采用IO多路复用机制,但是读写客户端依旧是同步IO(从内核缓冲区中拷贝数据的操作是同步操作),只能单线程依次读取客户端的数据,无法利用到多核CPU。
针对问题1,一方面需要业务人员去规避,一方面Redis在4.0推出了lazy-free机制,把bigkey释放内存的耗时操作放在了异步线程中执行,降低对主线程的影响。
针对问题2,Redis在6.0推出了多线程,可以在高并发场景下利用CPU多核多线程读写客户端数据,进一步提升server性能,当然,只是针对客户端的读写是并行的,每个命令的真正操作依旧是单线程的。