前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >面试题:Redis服务为何突然变慢了

面试题:Redis服务为何突然变慢了

作者头像
早起的鸟儿有虫吃
发布于 2025-04-26 12:27:58
发布于 2025-04-26 12:27:58
8800
代码可运行
举报
运行总次数:0
代码可运行

把面试官当陪练,在找工作中才会越战越勇

大家好我是小义同学,这是大厂面试拆解——项目实战系列的第4篇文章。

大家都是知道Redis纯内存数据库,处理速度很快,CPU架构,也会影响到 Redis 的性能

本文主要解决的一个问题在 Redis 为什么变慢,如何解决的?

一句话描述:Multi-Core CPU Optimization

  1. 【what】在多 CPU 插槽服务器上,Redis 的性能取决于 NUMA 配置和进程位置。
  2. 【how】Redis6.0通过配置文件对不同功能线程绑定不同cpu的物理核,对应命令 taskset 或 numactl,benchmarks 测试在同一个cpu,不同核效果最佳。
  3. 【why】:
  • 为了解决SMP架构(2-4个最佳)下不断增多的CPU Core导致的性能问题,NUMA架构应运而生
  • NUMA架构,数据缓存到不同cpu上不同核上 来回切换。
  • two different cores of the same CPU to benefit from the L3 cache

Redis线程类型

配置

功能描述

CPU 绑定核心

主线程

server_cpulist 0-7:2

事件循环,处理客户端连接和命令调度

0, 2, 4, 6

I/O 线程

server_cpulist 0-7:2

解析客户端的读写操作

0, 2, 4, 6

BIO 线程

bio_cpulist 1,3

执行耗时的后台任务(关闭文件、AOF fsync)

1, 3

AOF 重写子进程

aof_rewrite_cpulist 8-11

重写 AOF 文件,优化日志

8, 9, 10, 11

BGSAVE 子进程

bgsave_cpulist 1,10-11

保存内存快照到磁盘(RDB 文件)

1, 10, 11


下面是分析过程

大纲如下
大纲如下

大纲如下

你会疑问:Redis大家都说它快,什么情况变慢

  1. Redis 作为优秀的内存数据库,其拥有非常高的性能,单个实例的 OPS 能够达到 10W 左右
  2. Redis 事件循环基于 epoll/kqueue, 具有相当强的可扩展性。 Redis 已在超过 60,000 个连接的情况下进行了基准测试, 并且仍然能够维持 50,000 q/s 的吞吐量。

怎么会变慢呢?

一、确定Redis是否真的变慢了

1. 排查思路1: 看延迟

  • redis-cli 命令提供了–intrinsic-latency 120 选项, 该命令打印 120 秒内监测到的最大延迟,
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
redis-cli -h 127.0.0.1 -p 6379 --intrinsic-latency 120



Max latency so far: 110 microseconds.
Max latency so far: 119 microseconds.

redis-cli -h 127.0.0.1 -p 6379 --latency-history -i 1


min: 0, max: 1, avg: 0.13 (98 samples) -- 1.00 seconds range
min: 0, max: 1, avg: 0.08 (99 samples) -- 1.01 seconds range

  • 输出结果显示,60 秒内的最大响应延迟为 119 微秒(0.119 毫秒)

观察到的 Redis 运行时延迟是其基线性能的 2 倍及以上,就可以认定 Redis 变慢了

2. 排除思路:检查 网络是否瓶颈(排除不是)

- 一般要求:Redis 中,以 100000 q/s 的速率运行 4 KB 字符串的基准测试,实际将消耗 3.2 Gbit/s 的带宽,这很可能适合 10 Gbit/s 的链路。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

工具提供了服务器和客户端模式,来在两个主机之间执行网络吞吐量测试。

在服务端运行iperf,以在本机端口8899上启用iperf

输入命令iperf –s –p 8899 –i 1M 

iperf: option requires an argument -- M

iperf -c server IP -p 8899 -i 1 -t 10 -w 20K
------------------------------------------------------------
Client connecting to 172.20.0.113, TCP port 8899
TCP window size: 40.0 KByte (WARNING: requested 20.0 KByte)
------------------------------------------------------------
[  3] local 172.20.0.114 port 56796 connected with 172.20.0.113 port 12345
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 1.0 sec   614 MBytes  5.15 Gbits/sec
[  3]  1.0- 2.0 sec   622 MBytes  5.21 Gbits/sec
[  3]  2.0- 3.0 sec   646 MBytes  5.42 Gbits/sec
[  3]  3.0- 4.0 sec   644 MBytes  5.40 Gbits/sec


带宽满足

查缺补漏1 : 事件驱动:C10M是如何实现的?

  • TC P 是面向字节流的协议(拆分,大小并不受限制,无粘包问题),UDP 是面向报文的协议(不拆分)
  • 为什么建立连接是三次握手(无数据传输),而关闭连接需要四次挥手呢?(被动关闭缓冲器数据读完毕)
  • CPU 和内存的执行速度都是纳秒级的,无须考虑事件驱动,而磁盘和网络都可以采用事件驱动的异步方式处理。
  • TCP 四次挥手,可以变成三次吗?

二、解决办法: Redis6.0 如何通过配置支持 多核绑定

线程类型

配置

功能描述

CPU 绑定核心

主线程

server_cpulist 0-7:2

事件循环,处理客户端连接和命令调度

0, 2, 4, 6

I/O 线程

server_cpulist 0-7:2

解析客户端的读写操作

0, 2, 4, 6

BIO 线程

bio_cpulist 1,3

执行耗时的后台任务(关闭文件、AOF fsync)

1, 3

AOF 重写子进程

aof_rewrite_cpulist 8-11

重写 AOF 文件,优化日志

8, 9, 10, 11

BGSAVE 子进程

bgsave_cpulist 1,10-11

保存内存快照到磁盘(RDB 文件)

1, 10, 11

配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://raw.githubusercontent.com/redis/redis/6.0/redis.conf

# Redis Server and I/O threads are bound to CPU cores 0,2,4,6.
# 主线程:轮训方式 分配客户端请求到不同IO线程
#1.如何把待读客户端分配给IO线程执行
#2.
# IO线程: 客户端读取数据/将数据写回客户端
# 功能:1. 解析客户端发起读请求 IO_THREADS_OP_READ-->readQueryFromClient 
#      2  处理写数据到客户端 IO_THREADS_OP_WRITE-->writeToClient
# 数量:1-128个
# 命令:
#numactl --cpunodebind=0 --physcpubind=0,2,4,6 redis-server /path/to/redis.conf
# 思考一下:为什么不绑定固定的1个物理核上? 对cpu竞争严重
# numactl --hardware
#node 0 cpus: 0 1 2 3 4 5 6 7
server_cpulist 0-7:2

# Set bio threads to cpu affinity 1,3:
#Q1 bio_threads功能是? bioProcessBackgroundJobs
# 1. BIO_AOF_FSYNC--redis_fsync Aof持久化 
# 2 BIO_CLOSE_FILE 关闭文件 
#Q2 what is Aof 所有对数据库进行过写入的命令(及其参数)记录到 AOF file
bio_cpulist 1,3

# Set aof rewrite child process to cpu affinity 8,9,10,11:
# aof rewrite child
# number:1
# aof_rewrite_cpulist 8-11
#
# Set bgsave child process to cpu affinity 1,10,11
# bgsave child `fork` 之后的子进程能够获取父进程内存中的数据
# Redis 在执行 BGSAVE 操作时,将其子进程绑定到 CPU 核心 811 上运行
# bgsave_cpulist 1,10-11

2.1 代码如何实现的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://github.com/redis/redis/blob/6.2.17/src/rdb.c#L1440C9-L1440C28
int rdbSaveBackground(char *filename, rdbSaveInfo *rsi)
/* Child */
redisSetProcTitle("redis-rdb-bgsave");
redisSetCpuAffinity(server.bgsave_cpulist);
retval = rdbSave(filename,rsi);

int redisSetCpuAffinity(const char *cpulist) {
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);

    // 解析 cpulist,例如 "0-3,5"
    // 将解析后的 CPU 核心添加到 cpuset 中

    // 设置当前线程的 CPU 亲和性
    if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset) != 0) {
        // 错误处理
        return-1;
    }

    return0;
}

2.2 如何验证绑定生效

查看 NUMA 与核心分布

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
lscpu | grep "^NUMA node"

NUMA node(s):          2
NUMA node0 CPU(s):     0-5
NUMA node1 CPU(s):     6-11 

numactl --hardware
available: 2 nodes (0-1)
node 0 cpus:     0 1 2 3 4 5

node 1 cpus:     6 7 8 9 10 11

确认核心 8–11 属于同一 NUMA 节点,以保证内存本地性。

触发 AOF 重写redis 127.0.0.1:6379> BGREWRITEAOF Background append only file rewriting started

查找子进程 PID

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ ps -eLo pid,ppid,psr,comm | grep redis-server | grep BGREWRITEAOF
 2134  2100     8 redis-server: BGREWRITEAOF
 
 PSR       processor that process is currently assigned to

三、 为什么多核多Cpu会影响Redis的性能

直接看结果 来源 Redis核心技术与实战

图片来源:Redis核心技术与实战
图片来源:Redis核心技术与实战

✅ 什么是尾延迟?

假设你在点外卖,前 99 次下单都只用了 1 秒,但第 100 次突然用了 10 秒。虽然大多数时候都很快,但偶尔慢一下,这“偶尔的慢”就是所谓的尾延迟(Tail Latency)

假如 Redis 一共处理了 10000 个请求:

  • 9990 个用了 1 毫秒
  • 10 个用了 30 毫秒

那我们说:

  • 平均延迟 ≈ 1.03 毫秒(听起来很快)
  • P99 延迟 ≈ 30 毫秒(最慢的 1% 就是那几个拖后腿的) 在技术里,常用 P99
  • P99 延迟 = 99% 的请求比它快,它是最慢的 1%

✅ 什么是NUMA?

Non-uniform memory access (NUMA) is a [computer memory] design used in [multiprocessing], where the memory access time depends on the memory location relative to the processor.

非均匀内存访问 ( NUMA ) 是一种用于多处理系统的计算机内存设计,其内存访问时间取决于内存相对于处理器的位置

✅ 发生了什么,为什么程序偶尔慢的情况

从网卡读取请求,到处理请求举例,看数据的位置

  • 曾经做过测试,和访问 CPU Socket 本地内存相比,跨 CPU Socket 的内存访问延迟增加了 18%,这自然会导致 Redis 处理请求的延迟增加 哪里做验证【来自Redis核心技术与实战】
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
      Redis实例【我从这这读取】
           |
           |
      操作系统内核 <---- 从内核缓冲区读取网络数据【我在这里】
           |            |
           v            v
        网络数据 <---- 写入内核缓冲区 <---- 网络中断处理程序
           |                              |
           |                              |
           |                              v
           |                        从网卡读取数据
           |                              |
           |                              v
           |                            网卡



                           网络中断处理程序                      Redis 实例
                                 │                                 │
                           +-----+------+                +--------+-----+
                           | CPU Socket1 |───跨CPU Socket访问───| CPU Socket2 |
                           +------------+      【 总线 】      +------------+
                                 │                                 │
                                 ↓                                 ↓
        +----------------+      +----------------+        +----------------+
        |      内存      |      |      内存      |        |      内存      |
        |  +----------+  |      |                |        |                |
        |  | 网络数据 |  |      |    (空白)    |        |    (空白)    |
        |  +----------+  |      |                |        |                |
        +----------------+      +----------------+        +----------------+

  • 测试数据:来源网络
redis-benchmark results
redis-benchmark results
  • 绑定方式与收益:相同cpu相同的核 <不同的的cpu,不同的核 < 相同的cpu
  • two different cores of the same CPU to benefit from the L3 cache

使用 Swap 会导致 Redis 性能下降

  • swap 除非磁盘IO
  • swap 触发后影响的是 Redis 主 IO 线程,这会极大地增加 Redis 的响应时间
  • 一旦发生内存 swap,最直接的解决方法就是**增加机器内存

小总

cpu 对Redis 性能有影响

感谢阅读,如果你觉得这节课对你有一些启发,也欢迎把它分享给你的朋友。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端开发成长指南 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Redis28】Redis进阶:配置文件(二)
继续我们的配置文件的学习,上回我们已经学习完了整个 Redis 配置文件的前半部分,今天我们就向后半部分进发。这一部分的内容说实话有更多的内容是更偏门的,都不知道是干嘛用的。还是那句话,本着了解的态度,死磕也要过一遍,以后万一哪天用到了,再详细深入的研究也不迟。
硬核项目经理
2023/08/09
2590
【Redis28】Redis进阶:配置文件(二)
redis.conf翻译与配置(六)【redis6.0.6】
当散列有少量条目且最大条目不超过给定的阈值时,使用内存高效数据结构对其进行编码。可以使用以下指令配置这些阈值:
看、未来
2022/05/06
6750
Redis为什么变慢了?一文讲透如何排查Redis性能问题 | 万字长文
Redis 作为优秀的内存数据库,其拥有非常高的性能,单个实例的 OPS 能够达到 10W 左右。但也正因此如此,当我们在使用 Redis 时,如果发现操作延迟变大的情况,就会与我们的预期不符。
kunge
2021/01/28
1.4K0
Redis为什么变慢了?一文讲透如何排查Redis性能问题 | 万字长文
Redis实战:延迟问题排障指南
这时我们还是需要一个全面的排障流程,不能无厘头地进行优化;全面的排障流程可以帮助我们找到真正的根因和性能瓶颈,以及实施正确高效的优化方案
Kevinello
2023/03/05
1.1K0
Redis实战:延迟问题排障指南
Redis使用——Redis的redis.conf配置注释详解(四)
日常我们开发时,我们会遇到各种各样的奇奇怪怪的问题(踩坑o(╯□╰)o),这个常见问题系列就是我日常遇到的一些问题的记录文章系列,这里整理汇总后分享给大家,让其还在深坑中的小伙伴有绳索能爬出来。 同时在这里也欢迎大家把自己遇到的问题留言或私信给我,我看看其能否给大家解决。
cn華少
2022/01/11
4650
Redis 服务器
run_id:72ee9108ccfa7ea74bcf41c9b7575f327c3d64fd
子润先生
2021/07/02
1.1K0
redis.conf 7.0 配置和原理全解,生产王者必备
我是 Redis, 当程序员用指令 ./redis-server /path/to/redis.conf 把我启动的时候,第一个参数必须是redis.conf 文件的路径。
码哥字节
2023/01/04
3.6K0
第四章· Redis的事务、锁及管理命令
2)MySQL具有MVCC(多版本并发控制)的功能,这些都是根据事务的特性来完成的。
DriverZeng
2022/09/26
3850
第四章· Redis的事务、锁及管理命令
Redis变慢了,到底慢在哪儿?(3)
线上的Redis服务经经常有业务反馈响应慢的问题,针对这类问题,最好的分析方法是确定一个Redis的基准性能,然后去分析究竟什么原因导致的Redis变慢。
AsiaYe
2021/09/03
6820
[linux][redis]redis对cpu亲和性的支持
前言 redis在最近的版本中,开始了对多线程的支持。加上之前对多进程的支持,模型的复杂度也比过去复杂了不少。 redis本身又是一个对性能、延迟非常敏感的业务,多种因素都可能导致小问题。基于上述原因,作者对redis做了CPU亲和性的系统支持,并合入了upstream。 分析 代码 Redis 6.0.2版本中开始支持 https://github.com/antirez/redis/commit/ae306a3df6cf63b31a0814cb5393a9df59947d2e
皮振伟
2020/05/26
1.7K0
[linux][redis]redis对cpu亲和性的支持
Redis高可用之持久化
redis将数据保存在内存中,一旦Redis服务器被关闭,或者运行Redis服务的主机本身被关闭的话,储存在内存里面的数据就会丢失
良月柒
2019/03/20
8630
Redis高可用之持久化
Redis延迟问题全面排障指南
作者:kevine 前言 在 Redis 的实际使用过程中,我们经常会面对以下的场景: 在 Redis 上执行同样的命令,为什么有时响应很快,有时却很慢; 为什么 Redis 执行 GET、SET、DEL 命令耗时也很久; 为什么我的 Redis 突然慢了一波,之后又恢复正常了; 为什么我的 Redis 稳定运行了很久,突然从某个时间点开始变慢了。 这时我们还是需要一个全面的排障流程,不能无厘头地进行优化;全面的排障流程可以帮助我们找到真正的根因和性能瓶颈,以及实施正确高效的优化方案。 这篇文章我们就从可能
腾讯技术工程官方号
2023/04/29
1.4K0
Redis延迟问题全面排障指南
redis 学习指南
http://www.cnblogs.com/hoojo/p/4466024.html
bear_fish
2018/09/20
9070
redis 学习指南
感觉Redis变慢了,这些可能的原因你查了没 ?(下)
Redis变慢排查的上一篇,我们是基于Redis命令为入口,比如命令使用不得当,bigkey问题,以及集中过期问题来看现象和如何进行优化处理的,认真读过的同学想必大家对这些现象和处理方式有了比较深的印象。
小许code
2023/10/30
1.1K0
感觉Redis变慢了,这些可能的原因你查了没 ?(下)
Redis监控参数
查看redis pid的swap,均为0正常,如果多个其它则是正在交换,性能会下降 cat /proc/4476/smaps | grep Swap
陈不成i
2021/05/20
7080
lperf3-网络测试工具
Iperf3 是一个网络性能测试工具。Iperf可以测试最大TCP和UDP带宽性能,具有多种参数和UDP特性,可以根据需要调整,可以报告带宽、延迟抖动和数据包丢失.对于每个测试,它都会报告带宽,丢包和其他参数,可在Windows、Mac OS X、Linux、FreeBSD等各种平台使用,是一个简单又实用的小工具。
胡齐
2019/11/19
8K0
Redis持久化 - RDB和AOF
持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。 持久化Redis所有数据保持在内存中,对数据的更新将异步地保存到磁盘上。
BUG弄潮儿
2020/09/23
3860
Redis持久化 - RDB和AOF
由面试题“Redis是否为单线程”引发的思考
很多人都遇到过这么一道面试题:Redis是单线程还是多线程?这个问题既简单又复杂。说他简单是因为大多数人都知道Redis是单线程,说复杂是因为这个答案其实并不准确。
默 语
2024/11/20
1030
由面试题“Redis是否为单线程”引发的思考
Redis基础—了解Redis是如何做数据持久化的
之前的文章介绍了Redis的简单数据结构的相关使用和底层原理,这篇文章我们就来聊一下Redis应该如何保证高可用。
SH的全栈笔记
2020/11/13
3520
Redis服务与连接那些事儿
这样虽然是启动了,但是这个终端却用不了了,我个人并不是很喜欢。那么有没有可以让他既可以运行,而且保证不会占用我们的终端呢
PayneWu
2021/01/25
8810
相关推荐
【Redis28】Redis进阶:配置文件(二)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档