主流CPU架构

一个 CPU 处理器中一般有多个运行核心,我们把一个运行核心称为一个物理核。每个物理核都有私有的一级缓存(L1 cache)以及二级缓存(L2 cache),即其他物理核无法访问。

不同的物理核还会共享一个共同的三级缓存(L3 cache)

现在主流的 CPU 处理器中,每个物理核通常都会运行两个超线程,也叫作逻辑核。同一个物理核的逻辑核会共享使用 L1、L2 缓存。

image-20230405110450816

一个CPU会有多个物理核,而一个服务器上可能会有多个CPU,如下图所示:

image-20230405110614748

在上图的这种CPU架构中,Redis可以在不同的CPU上运行,意味着它可以现在Socket1上运行,然后被调度到Socket2上执行。

这里就会出现问题,如果应用程序先在一个 Socket 上运行,并且把数据保存到了内存,然后被调度到另一个 Socket 上运行,此时,应用程序再进行内存访问时,就需要访问之前 Socket 上连接的内存,这种访问属于远端内存访问和访问 Socket 直接连接的内存相比,远端内存访问会增加应用程序的延迟。

每一个CPU会管理一部分内存,所以存在从Socket1切换到Socket2上存在远端访问。

CPU多核对Redis的影响

在一个 CPU 核上运行时,应用程序需要记录自身使用的软硬件资源信息(例如栈指针、CPU 核的寄存器值等),我们把这些信息称为运行时信息。同时,应用程序访问最频繁的指令和数据还会被缓存到 L1、L2 缓存上,以便提升执行速度。

Redis在不同cpu之前进行切换时,另一个cpu上并没有redis之前运行时频繁访问的指令和数据,所以这些数据都需要重新从L3缓存甚至是内存中加载,Redis需要等到这些加载完才处理请求,所以会导致较高的延迟。

如果在 CPU 多核场景下,Redis 实例被频繁调度到不同 CPU 核上运行的话,那么,对 Redis 实例的请求处理时间影响就更大了。每调度一次,一些请求就会受到运行时信息、指令和数据重新加载过程的影响,这就会导致某些请求的延迟明显高于其他请求

解决方案

可以把Redis实例绑定到一个CPU的一个物理核上面。

这里是因为同一个CPU里面会有多个物理核,而物理核的L1和L2缓存是私有的,如果在同一个CPU的不同物理核切换,也会导致一些命令需要重新加载。