Redis:性能风险之CPU核和NUMA架构的影响

【关于作者】

关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(https://0522-isniceday.top/)联系我

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5IRTiCXe-1680957421197)(https://zhangyuxiangplus.oss-cn-hangzhou.aliyuncs.com/boke/CPU核和NUMA架构的影响.png)]

1.主流CPU架构

物理核:CPU中一般有多个运行核心,一个运行核心称作物理核,每个物理核都可以独立的运行程序

一级缓存(Level 1 cache,简称L1 cache):为每个物理核所私有,包括一级指令缓存和一级数据缓存

二级缓存(Level 2 cache,简称L2 cache):为每个物理核所私有

物理核的私有缓存:指缓存空间只能被当前物理核所使用,其他物理核无法对该缓存空间的数据进行读取。一级、二级都是私有缓存,并且物理核访问L1和L2非常快,一般为10纳秒,但是L1和L2的空间非常小,一般为KB级别,如果L1或L2中找不到数据那么就只能从访存查找,速度大约为百纳秒。

物理核具体架构如下:

img

三级缓存(Level 3 cache,简称L3 cache):不同的物理核可以共享L3缓存,一般为几十MB,能够缓存更多数据,当L1、L2无法查询到数据时,可以从L3查找

逻辑核:每个物理核中会运行两个超线程,也叫逻辑核。同一个物理核的逻辑核会共享L1、L2

具体关系如下:

img

处理器:主流服务器上通常会有多个处理器(CPU Socket),而一个处理器上可能会有10-20个物理核(L1、L2缓存),L3缓存,以及连接的内存(不同处理器会连接不同的内存?),不同处理器通过主线连接

img

多CPU架构上,redis可以在不同的处理器上运行。例如Redis可以先在Socket 1上运行一段时间,然后再被调度到Socket 2上运行。

远端内存访问:redis在CPU Socket 1上运行并将数据存储到了其所连接的内存,这个时候被调度到Socket 2运行,此时如果读取数据需要连接到Socket 1的内存中取读取,这就叫远端内存访问。

非同一内存访问架构(Non-Uniform Memory Access,NUMA架构):多CPU架构下,应用程序访问直连内存和远端内存的延迟并不会一致,远端内存访问会增加应用程序的延迟,这个架构就叫非同一内存访问架构。不同Socket通过总线进行通信,不同物理核之间通过QPI(Quick Path Interconnect)进行通信

2.CPU多核对Redis的性能影响

运行时信息:在CPU核上运行时,应用程序需要记录自身用到的软硬件资源(例如栈指针,用到的寄存器的值等),这些信息称为运行时信息。同时应用程序访问最频繁的指令和数据会缓存在L1、L2缓存

多核场景下:应用程序可能会需要到一个新的核上运行,此时就需要重新加载运行时信息(context switch,上下文切换),并且重新加载L1、L2缓存的数据,这个过程会导致程序的运行时间增加

context switch :运行数据及L1、L2的重新加载就是上下文切换,频繁的context switch会影响应用程序,因为切换是需要耗费时间用于L1、L2或者L3缓存及运行时信息的重新加载,并且redis实例需要等待加载完成才能够处理请求。

如何避免上下文切换呢?

使用taskset命令将redis实例绑定在一个核上运行, -c 设置绑定的编号

taskset -c 0 ./redis-server

3.CPU的NUMA架构对Redis的性能影响

3.1.NUMA架构

由于采用NUMA架构的原因,所有实例会优先使用这一个节点的内存,当这个节点内存不足时,再经过总线去申请另一个CPU Socket下的内存,此时也会增加延迟。

3.2.NUMA架构对Redis的影响

如果网络中断处理程序和Redis实例各自所绑的CPU核不在同一个CPU Socket上,那么,Redis实例读取网络数据时,就需要跨CPU Socket访问内存,这个过程会花费较多时间

img

在CPU多核的场景下,用taskset命令把Redis实例和一个核绑定,可以减少Redis实例在不同核上被来回调度执行的开销,避免较高的尾延迟;在多CPU的NUMA架构下,如果你对网络中断程序做了绑核操作,建议你同时把Redis实例和网络中断程序绑在同一个CPU Socket的不同核上,这样可以避免Redis跨Socket访问内存中的网络数据的时间开销

为了提升Redis的网络性能,我们有时还会把网络中断处理程序和CPU核绑定。在这种情况下,如果服务器使用的是NUMA架构,Redis实例一旦被调度到和中断处理程序不在同一个CPU Socket,就要跨CPU Socket访问网络数据,这就会降低Redis的性能。所以,我建议你把Redis实例和网络中断处理程序绑在同一个CPU Socket下的不同核上,这样可以提升Redis的运行性能

3.3.绑核所带来的风险及解决办法

当我们把Redis实例绑到一个CPU逻辑核上时,就会导致子进程、后台线程和Redis主线程竞争CPU资源,一旦子进程或后台线程占用CPU时,主线程就会被阻塞,导致Redis请求延迟增加

方案一:一个Redis实例对应绑一个物理核

在给Redis实例绑核时,我们不要把一个实例和一个逻辑核绑定,而要和一个物理核绑定,也就是说,把一个物理核的2个逻辑核都用上,这样,Redis的主线程、子进程和后台线程可以共享使用一个物理核上的两个逻辑核

方案二:优化Redis源码

如果你很熟悉Redis的源码,就可以在源码中增加绑核操作,把子进程和后台线程绑到不同的核上,这样可以避免对主线程的CPU资源竞争。不过,如果你不熟悉Redis源码,也不用太担心,Redis 6.0出来后,可以支持CPU核绑定的配置操作了,我将在第38讲中向你介绍Redis 6.0的最新特性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈哈张大侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值