7
7
8
8
> 本文整理完善自:https://mp.weixin.qq.com/s/0Nqfq_eQrUb12QH6eBbHXA ,作者:阿Q说代码
9
9
10
- ## O(n) 命令阻塞
10
+ 这篇文章会详细总结一下可能导致 Redis 阻塞的情况,这些情况也是影响 Redis 性能的关键因素,使用 Redis 的时候应该格外注意!
11
+
12
+ ## O(n) 命令
11
13
12
14
使用` O(n) ` 命令可能会导致阻塞,例如` keys * ` 、` hgetall ` 、` lrange ` 、` smembers ` 、` zrange ` 、` sinter ` 、` sunion ` 命令。这些命令时间复杂度是 O(n),有时候也会全表扫描,随着 n 的增大耗时也会越大从而导致客户端阻塞。
13
15
14
16
不过, 这些命令并不是一定不能使用,但是需要明确 N 的值。有遍历的需求可以使用 ` hscan ` 、` sscan ` 、` zscan ` 代替。
15
17
16
- ## SAVE 创建 RDB 快照阻塞
18
+ ## SAVE 创建 RDB 快照
17
19
18
20
Redis 提供了两个命令来生成 RDB 快照文件:
19
21
@@ -22,7 +24,9 @@ Redis 提供了两个命令来生成 RDB 快照文件:
22
24
23
25
默认情况下,Redis 默认配置会使用 ` bgsave ` 命令。如果手动使用 ` save ` 命令生成 RDB 快照文件的话,就会阻塞主线程。
24
26
25
- ## AOF 日志记录阻塞
27
+ ## AOF
28
+
29
+ ### AOF 日志记录阻塞
26
30
27
31
Redis AOF 持久化机制是在执行完命令之后再记录日志,这和关系型数据库(如 MySQL)通常都是执行命令之前记录日志(方便故障恢复)不同。
28
32
@@ -38,21 +42,21 @@ Redis AOF 持久化机制是在执行完命令之后再记录日志,这和关
38
42
- 如果刚执行完命令 Redis 就宕机会导致对应的修改丢失;
39
43
- ** 可能会阻塞后续其他命令的执行(AOF 记录日志是在 Redis 主线程中进行的)** 。
40
44
41
- ## AOF 刷盘阻塞
45
+ ### AOF 刷盘阻塞
42
46
43
47
开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到 AOF 缓冲区 ` server.aof_buf ` 中,然后再根据 ` appendfsync ` 配置来决定何时将其同步到硬盘中的 AOF 文件。
44
48
45
49
在 Redis 的配置文件中存在三种不同的 AOF 持久化方式( ` fsync ` 策略),它们分别是:
46
50
47
- ``` bash
48
- appendfsync always # 每次有数据修改发生时都会调用fsync函数同步AOF文件,fsync完成后线程返回,这样会严重降低Redis的速度
49
- appendfsync everysec # 每秒钟调用fsync函数同步一次AOF文件
50
- appendfsync no # 让操作系统决定何时进行同步,一般为30秒一次
51
- ```
51
+ 1 . ` appendfsync always ` :主线程调用 ` write ` 执行写操作后,后台线程( ` aof_fsync ` 线程)立即会调用 ` fsync ` 函数同步 AOF 文件(刷盘),` fsync ` 完成后线程返回,这样会严重降低 Redis 的性能(` write ` + ` fsync ` )。
52
+ 2 . ` appendfsync everysec ` :主线程调用 ` write ` 执行写操作后立即返回,由后台线程( ` aof_fsync ` 线程)每秒钟调用 ` fsync ` 函数(系统调用)同步一次 AOF 文件(` write ` +` fsync ` ,` fsync ` 间隔为 1 秒)
53
+ 3 . ` appendfsync no ` :主线程调用 ` write ` 执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(` write ` 但不` fsync ` ,` fsync ` 的时机由操作系统决定)。
52
54
53
- 当调用 fsync 函数同步 AOF 文件时,需要等待,直到写入完成。当磁盘压力太大的时候,主线程可能会被阻塞 。
55
+ 当后台线程( ` aof_fsync ` 线程)调用 ` fsync ` 函数同步 AOF 文件时,需要等待,直到写入完成。当磁盘压力太大的时候,会导致 ` fsync ` 操作发生阻塞,主线程调用 ` write ` 函数时也会被阻塞。 ` fsync ` 完成后,主线程执行 ` write ` 才能成功返回 。
54
56
55
- ## AOF 重写阻塞
57
+ 关于 AOF 工作流程的详细介绍可以查看:[ Redis持久化机制详解] ( ./redis-persistence.md ) ,有助于理解 AOF 刷盘阻塞。
58
+
59
+ ### AOF 重写阻塞
56
60
57
61
1 . fork 出一条子线程来将文件重写,在执行 ` BGREWRITEAOF ` 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子线程创建新 AOF 文件期间,记录服务器执行的所有写命令。
58
62
2 . 当子线程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。
@@ -62,7 +66,7 @@ appendfsync no #让操作系统决定何时进行同步,一般为30秒
62
66
63
67
相关阅读:[ Redis AOF重写阻塞问题分析] ( https://cloud.tencent.com/developer/article/1633077 ) 。
64
68
65
- ## 大 Key 问题
69
+ ## 大 Key
66
70
67
71
如果一个 key 对应的 value 所占用的内存比较大,那这个 key 就可以看作是 bigkey。具体多大才算大呢?有一个不是特别精确的参考标准:string 类型的 value 超过 10 kb,复合类型的 value 包含的元素超过 5000 个(对于复合类型的 value 来说,不一定包含的元素越多,占用的内存就越多)。
68
72
@@ -105,3 +109,52 @@ Redis 集群可以进行节点的动态扩容缩容,这一过程目前还处
105
109
106
110
执行迁移时,两端的 Redis 均会进入时长不等的阻塞状态,对于小 Key,该时间可以忽略不计,但如果一旦 Key 的内存使用过大,严重的时候会触发集群内的故障转移,造成不必要的切换。
107
111
112
+ ## Swap(内存交换)
113
+
114
+ 什么是 Swap?Swap 直译过来是交换的意思,Linux中的Swap常被称为内存交换或者交换分区。类似于 Windows 中的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。因此,Swap 分区的作用就是牺牲硬盘,增加内存,解决 VPS 内存不够用或者爆满的问题。
115
+
116
+ Swap 对于Redis来说是非常致命的,Redis保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把Redis使用的部分内存换出硬盘,由于内存与硬盘读写的速度并几个数量级,会导致发生交换后的Redis性能急剧下降。
117
+
118
+ 识别 Redis 发生 Swap 的检查方法如下:
119
+
120
+ 1、查询Redis进程号
121
+
122
+ ``` bash
123
+ reids-cli -p 6383 info server | grep process_id
124
+ process_id: 4476
125
+ ```
126
+
127
+ 2、根据进程号查询内存交换信息
128
+
129
+ ``` bash
130
+ cat /proc/4476/smaps | grep Swap
131
+ Swap: 0kB
132
+ Swap: 0kB
133
+ Swap: 4kB
134
+ Swap: 0kB
135
+ Swap: 0kB
136
+ .....
137
+ ```
138
+
139
+ 如果交换量都是0KB或者个别的是4KB,则正常。
140
+
141
+ 预防内存交换的方法:
142
+
143
+ - 保证机器充足的可用内存
144
+ - 确保所有Redis实例设置最大可用内存(maxmemory),防止极端情况Redis内存不可控的增长
145
+ - 降低系统使用swap优先级,如` echo 10 > /proc/sys/vm/swappiness `
146
+
147
+ ## CPU 竞争
148
+
149
+ Redis是典型的CPU密集型应用,不建议和其他多核CPU密集型服务部署在一起。当其他进程过度消耗CPU时,将严重影响Redis的吞吐量。
150
+
151
+ 可以通过` reids-cli --stat ` 获取当前Redis使用情况。通过` top ` 命令获取进程对CPU的利用率等信息 通过` info commandstats ` 统计信息分析出命令不合理开销时间,查看是否是因为高算法复杂度或者过度的内存优化问题。
152
+
153
+ ## 网络问题
154
+
155
+ 连接拒绝、网络延迟,网卡软中断等网络问题也可能会导致 Redis 阻塞。
156
+
157
+ ## 参考
158
+
159
+ - Redis阻塞的6大类场景分析与总结:https://mp.weixin.qq.com/s/eaZCEtTjTuEmXfUubVHjew
160
+ - Redis开发与运维笔记-Redis的噩梦-阻塞:https://mp.weixin.qq.com/s/TDbpz9oLH6ifVv6ewqgSgA
0 commit comments