欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

关于redis单线程的分析

程序员文章站 2022-03-28 12:48:42
redis为什么那么快?结论有三点,大家都知道,这里主要是分析。 首先第一点 redis是内存访问的,所以快 当然这个大家都知道,所以不是重点 io密集型和cpu密集型 一般我们把任务分为io密集型和cpu密集型 io密集型 IO密集型指的是系统的CPU性能相对硬盘、内存要好很多,此时,系统运作,大 ......

redis为什么那么快?结论有三点,大家都知道,这里主要是分析。

首先第一点

redis是内存访问的,所以快

当然这个大家都知道,所以不是重点


 

io密集型和cpu密集型

一般我们把任务分为io密集型cpu密集型

 

io密集型

  • io密集型指的是系统的cpu性能相对硬盘、内存要好很多,此时,系统运作,大部分的状况是cpu在等i/o (硬盘/内存) 的读/写操作,此时cpu loading并不高。
  • 对于io密集型的任务,它的主要时间都在磁盘io上,而io本身在发出中断告知cpu后,cpu只需要短暂的处理一下,之后就由dma(详见附录)负责数据传输,整个过程对cpu的利用率很低。因此我们需要开更多的线程去充分利用cpu。即一般线程数 = cpu核心数 * 2,如数据库连接池

 

cpu密集型

  • cpu密集型也叫计算密集型,指的是系统的硬盘、内存性能相对cpu要好很多,此时,系统运作大部分的状况是cpu loading 100%,cpu要读/写i/o(硬盘/内存),i/o在很短的时间就可以完成,而cpu还有许多运算要处理,cpu loading很高。
  • 对于cpu密集型的任务,它对cpu的利用率很高,所以不需要开更多的线程去提高cpu利用率。假如增加线程,只会引起线程的频繁切换导致本来就不够用的cpu更加不够用。所以一般是线程数 = cpu核心数 + 1

 


 

redis的瓶颈在哪里

redis基本都在进行内存io,那它的瓶颈在io上吗?

redis在网络io上使用epoll实现了一个io多路复用的reactor模型,epoll是非阻塞io,所以避免了cpu阻塞在io上,所以它不是io密集型,瓶颈不在于等待io导致cpu利用率不高,不需要多个线程来屏蔽等待io执行完成的时间。当然redis的io利用率很高,但是io利用率高并不代表它是io密集型,因为它瓶颈不在等待io上。

 

所以第二点

redis在网络io上使用epoll实现了一个io多路复用的reactor模型使得cpu利用率更高,浪费在io上的时间更少

redis并不需要多线程来提高cpu利用率减少io等待时间,并且单线程架构也比较容易实现,所以顺理成章就采用了单线程架构。

关于epoll可以看我的这篇文章:

第三点

由于采用了单线程架构,避免了线程线程切换产生的消耗

因为一次cpu上下文的切换大概在 1500ns 左右。

从内存中读取 1mb 的连续数据,耗时大约为 250us,假设1mb的数据由多个线程读取了1000次,那么就有1000次时间上下文的切换,

那么就有1500ns * 1000 = 1500us ,我单线程的读完1mb数据才250us ,你光时间上下文的切换就用了1500us了,我还不算你每次读一点数据 的时间

 

那么redis是cpu密集型吗?答案是否定的。

redis也不是cpu密集型。大多数情况下redis机器上的cpu是很够用的。

 

redis的瓶颈在于内存大小和网络带宽。

 

如果想要更充分的利用多核cpu,可以采用多个redis实例的方法,同时为了减少线程争用,可以将实例和cpu绑定的方法。

但是如果做了cpu绑定,在rdb和aof时子进程会与父进程共享使用一个cpu。子进程重写时对单核cpu使用率通常在90%以上,父进程与子进程将产生激烈cpu竞争,极大影响redis稳定性。(解决方法不清楚,也许多绑定一个cpu会好点?)

 


 

附录

dma

dma 传输将数据从一个地址空间复制到另外一个地址空间。当cpu 初始化这个传输动作,传输动作本身是由 dma 控制器来实行和完成。

典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。例如内存移到磁盘。

 

最后惯例附一图:

关于redis单线程的分析

 


参考资料: