文章系转载,便于分类和归纳,源文地址:https://www.yisu.com/zixun/672271.html
绑定 CPU
Redis 6.0 开始支持绑定 CPU,可以有效减少线程上下文切换。
CPU 亲和性(CPU Affinity)是一种调度属性,它将一个进程或线程,「绑定」到一个或一组 CPU 上。也称为 CPU 绑定。
设置 CPU 亲和性可以一定程度避免 CPU 上下文切换,提高 CPU L1、L2 Cache 命中率。
早期「SMP」架构下,每个 CPU 通过 BUS 总线共享资源。CPU 绑定意义不大。
![](https://i-blog.csdnimg.cn/blog_migrate/01718fcbeb8276025939eec9b730a944.png)
而在当前主流的「NUMA」架构下,每个 CPU 有自己的本地内存。访问本地内存有更快的速度。而访问其他 CPU 内存会导致较大的延迟。这时,CPU 绑定对系统运行速度的提升有较大的意义。
![](https://i-blog.csdnimg.cn/blog_migrate/b5c98f45122b354ec80ba58179179254.png)
现实中的 NUMA 架构比上图更复杂,通常会将 CPU 分组,若干个 CPU 分配一组内存,称为 「node」。
你可以通过 「numactl -H 」 命令来查看 NUMA 硬件信息。
$ numactl -H
available: 2 nodes (0-1)node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
node 0 size: 32143 MB
node 0 free: 26681 MB
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
node 1 size: 32309 MB
node 1 free: 24958 MB
node distances:
node 0 1
0: 10 21
1: 21 10
上图中可以得知该机器有 40 个 CPU,分组为 2 个 node。
node distances 是一个二维矩阵,表示 node 之间 「访问距离」,10 为基准值。上述命令中可以得知,node 自身访问,距离是 10。跨 node 访问,如 node 0 访问 node 1 距离为 21。说明该机器「跨 node 访问速度」比「node 自身访问速度」慢 2.1 倍。
其实,早在 2015 年,有人提出 Redis 需要支持设置 CPU 亲和性,而当时的 Redis 还没有支持 IO 多线程,该提议搁置。
而 Redis 6.0 引入 IO 多线程。同时,也支持了设置 CPU 亲和性。
我画了一张 Redis 6.0 线程家族供你参考。
![](https://i-blog.csdnimg.cn/blog_migrate/ffa0c59791669eb7e7454433f92c3806.png)
上图可分为 3 个模块
- 主线程和 IO 线程:负责命令读取、解析、结果返回。命令执行由主线程完成。
- bio 线程:负责执行耗时的异步任务,如 close fd。
- 后台进程:fork 子进程来执行耗时的命令。
Redis 支持分别配置上述模块的 CPU 亲和度。你可以在 redis.conf 找到以下配置(该配置需手动开启)。
# IO 线程(包含主线程)绑定到 CPU 0、2、4、6
server_cpulist 0-7:2
# bio 线程绑定到 CPU 1、3
bio_cpulist 1,3
# aof rewrite 后台进程绑定到 CPU 8、9、10、11
aof_rewrite_cpulist 8-11
# bgsave 后台进程绑定到 CPU 1、10、11
bgsave_cpulist 1,10-11
我在上述机器,针对 IO 线程和主线程,进行如下测试:
首先,开启 IO 线程配置。
# 主线程 + 3 个 IO 线程io-threads-do-reads yes
# IO 线程开启读和解析命令功能
io-threads 4
测试如下三种场景:
- 不开启 CPU 绑定配置。
- 绑定到不同 node。
「server_cpulist 0,1,2,3」 - 绑定到相同 node。
「server_cpulist 0,2,4,6」
通过 redis-benchmark 对 get 命令进行基准测试,每种场景执行 3 次。
$ redis-benchmark -n 5000000 -c 50 -t get --threads 4
结果如下:
1.不开启 CPU 绑定配置
throughput summary: 248818.11 requests per second
throughput summary: 248694.36 requests per second
throughput summary: 249004.00 requests per second
2.绑定不同 node
throughput summary: 248880.03 requests per second
throughput summary: 248447.20 requests per second
throughput summary: 248818.11 requests per second
3.绑定相同 node
throughput summary: 284414.09 requests per second
throughput summary: 284333.25 requests per second
throughput summary: 265252.00 requests per second
根据测试结果,绑定到同一个 node,qps 大约提升 15%
使用绑定 CPU,你需要注意以下几点:
- Linux 下,你可以使用 「numactl --hardware」 查看硬件布局,确保支持并开启 NUMA。
- 线程要尽可能分布在 「不同的 CPU,相同的 node」,设置 CPU 亲和度才有效。否则会造成频繁上下文切换和远距离内存访问。
- 你要熟悉 CPU 架构,做好充分的测试。否则可能适得其反,导致 Redis 性能下降。