undefined

Redis的单线程

Redis的单线程主要指:Redis 的网络IO和键值对读写是由一个线程来完成的,这也是redis 对外提供键值存储服务的主要流程。但redis的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。

多线程无法线性提升系统吞吐量的原因:一个关键的瓶颈在于,系统中通常会存在被多线程同步访问的共享资源。为了保证资源的正确性,额外的机制会带来额外的开销。

1. 单线程Redis快的原因

  1. Redis 的大部分操作在内存上完成,再加上它采用了高效的数据结构
  2. Redis 采用了多路复用机制(epoll),使其在网络IO中能并发处理大量的客户端请求,实现高吞吐率。

2. 单线程处理IO请求性能瓶颈

  • 任意一个请求在 server 中一旦发生耗时,都会影响整个 server 的性能,也就是说后面的请求要等到前面的耗时请求处理完成,自己才能被处理到。耗时的操作如下:

    1. 操作bigkey:写入一个bigkey在分配内存时需要消耗更多的时间,同样,删除bigkey释放内存同样会产生耗时;
    2. 使用复杂度过高的命令:例如SORT/SUNION/ZUNIONSTORE,或者O(N)命令,但是N很大,例如lrange key 0 -1一次查询全量数据;
    3. 大量key集中过期:Redis的过期机制也是在主线程中执行的,大量key集中过期会导致处理一个请求时,耗时都在删除过期key,耗时变长;
    4. 淘汰策略:淘汰策略也是在主线程执行的,当内存超过Redis内存上限后,每次写入都需要淘汰一些key,也会造成耗时变长;
    5. AOF刷盘开启always机制:每次写入都需要把这个操作刷到磁盘,写磁盘的速度远比写内存慢,会拖慢Redis的性能;
    6. 主从全量同步生成RDB:虽然采用fork子进程生成数据快照,但fork这一瞬间也是会阻塞整个线程的,实例越大,阻塞时间越久;
  • 并发量非常大时,单线程读写客户端IO数据存在性能瓶颈,虽然采用IO多路复用机制,但是读写客户端数据依旧是同步IO,只能单线程依次读取客户端的数据,无法利用到CPU多核。注:这里的同步IO 并不是指整个网络IO是同步的,而是指从内核缓冲区拷贝数据的操作是同步操作。