# 033. redis 在实践中的一些常见问题以及优化思路(包含 linux 内核参数优化)
基本讲解到现在,大家其实直接到公司里,就可以去搭建 redis 了
其实有些东西,也许没有讲解到台细节的一些东西,比如一些参数的设置,这个是因为不同的公司,不同的业务,不同的数据量,可能要调节的参数不同
到这里为止,大家就差不多了,按照这个思路,去搭建 redis 支撑高并发、高可用、海量数据的架构,部署。可以用公司里的一些已有的数据,导入进去,几百万,一千万,导入进去,做各种压力测试(使用 redis-benchmark 就可以)、性能、并发、QPS,高可用的演练,每台机器最大能存储多少数据量,横向扩容支撑更多数据
基于测试环境还有测试数据,做各种演练,去摸索一些最适合自己的一些细节的东西
旁白
你说你靠一套课程,搞定一个技术 100% 的所有的东西,几乎是不可能的
师傅领进门,修行在个人
一套好的课程,唯一的判断标准,就是在这个价格下,能教会你值得这个价格的一些技术和架构等等知识,是你从其他地方没法学到的,或者自己去学要耗费几倍的时间摸索的
这个课程的价值就已经达到了
你说你花了几百块钱,买了个课程,要求,课程,学完,立即就是独孤九剑,直接到公司里各种问题都能轻松解决
这个世界上,不存在这种课程,所以你需要有一个合理的价值观,我们大家才能有一个非常好的良性的互动的过程
之前也左右一些在线课程,比如 spark 等等课程,就有人说为什么没有成为顶尖高手,这就很尴尬了
实际学了课程去做项目,100% 会遇到大量自己没想到的问题,遇到了首先就自己尝试去解决,遇到问题,才是你的经验积累
遇到了问题,加我的 QQ,然后跟我咨询咨询,我给你看看,也是可以的
比如之前的 spark,elasticsearch,java 架构课程,基本上 70%~80% 的问题,我都可以帮你搞定,当然是我能做到的,有些不在现场也许也搞不定,就需要你自己搞定了
# fork 耗时导致高并发请求延时
RDB 和 AOF 的时候会存在 RDB 快照生成、AOF rewrite,耗费磁盘 IO 的过程
主进程 fork 子进程的时候,子进程是需要拷贝父进程的空间内存页表的,也是会耗费一定的时间的
一般来说,如果父进程内存有 1 个 G 的数据,那么 fork 可能会耗费在 20ms 左右,如果是 10G~30G,那么就会耗费 20 * 10,甚至 20 * 30,也就是几百毫秒的时间
info stats 中的 latest_fork_usec,可以看到最近一次 fork 的时长
redis 单机 QPS 一般在几万,fork 可能一下子就会拖慢几万条操作的请求时长,从几毫秒变成 1 秒
优化思路:fork 耗时跟 redis 主进程的内存有关系,一般控制 redis 的内存在 10GB 以内;否则 slave -> master 在全量复制等时候就可能会出现一些问题
# AOF 的阻塞问题
redis 将数据写入 AOF 缓冲区,单独开一个线程做 fsync 操作,每秒一次
但是 redis 主线程会检查两次 fsync 的时间,如果距离上次 fsync 时间超过了 2 秒,那么写请求就会阻塞
everysec,最多丢失 2 秒的数据
一旦 fsync 超过 2 秒的延时,整个 redis 就被拖慢
优化思路:优化硬盘写入速度,建议采用 SSD,不要用普通的机械硬盘,SSD 大幅度提升磁盘读写的速度
# 主从复制延迟问题
主从复制可能会超时严重,这个时候需要良好的监控和报警机制
在 info replication 中,可以看到 master 和 slave 复制的 offset,做一个差值就可以看到对应的延迟量,如果延迟过多,那么就进行报警(可以写一个 shell 脚本去监控)
# 主从复制风暴问题
如果一下子让多个 slave 从 master 去执行全量复制,一份大的 rdb 同时发送到多个 slave,会导致网络带宽被严重占用
如果一个 master 真的要挂载多个 slave,那尽量用树状结构,不要用星型结构
树,意思就是说,让一个节点下面的 slave 不要太多,可以通过 replication 的方式去配置
如果是在 redis cluster 中应该不会存在这种问题
# vm.overcommit_memory
该信息是在 redis 启动的时候一些警告信息,这些警告信息可以通过调整 linux 内核配置达到性能的优化
[root@eshop-cache03 ~]# cat /var/log/redis/7008.log
1418:M 24 Mar 13:10:59.513 * Increased maximum number of open files to 10032 (it was originally set to 1024).
1418:M 24 Mar 13:10:59.513 # Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.
1418:M 24 Mar 13:10:59.513 * No cluster configuration found, I'm 728e473d6e5e36ddb051c600c7708f23733c46f7
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.8 (00000000/0) 32 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in cluster mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 7008
| `-._ `._ / _.-' | PID: 1418
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
1418:M 24 Mar 13:10:59.626 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1418:M 24 Mar 13:10:59.626 # Server started, Redis version 3.2.8
1418:M 24 Mar 13:10:59.626 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- 0: 检查有没有足够内存,没有的话申请内存失败
- 1: 允许使用内存直到用完为止
- 2: 内存地址空间不能超过 swap + 50%
如果是 0 的话,可能导致类似 fork 等操作执行失败,申请不到足够的内存空间
下面的命令在日志里面就已经提示出来了
cat /proc/sys/vm/overcommit_memory
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1
2
3
# swapiness
# 查看 linux 内核版本
cat /proc/version
2
如果 linux 内核版本 ❤️.5,那么 swapiness 设置为0,这样系统宁愿 swap也不会 oom killer(杀掉进程)
如果 linux 内核版本 >=3.5,那么 swapiness 设置为 1,这样系统宁愿 swap 也不会 oom killer
保证 redis 不会被杀掉
echo 0 > /proc/sys/vm/swappiness
echo vm.swapiness=0 >> /etc/sysctl.conf
2
# 最大打开文件句柄
Increased maximum number of open files to 10032 (it was originally set to 1024).
# 如果该命令不可用,可以去百度搜索不同的版本命令
ulimit -n 10032 10032
2
自己去上网搜一下,不同的操作系统,版本,设置的方式都不太一样
# tcp backlog
WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
cat /proc/sys/net/core/somaxconn
echo 511 > /proc/sys/net/core/somaxconn
2