深入学习Redis:Redis常见问题以及优化方案

标签: Redis  

常见问题以及优化方案

1. fork耗时导致高并发请求延时

一般来说,如果父进程内存有1个G的数据,那么fork可能会耗费在20ms左右,如果是10G~30G,那么就会耗费20 * 10,甚至20 * 30,也就是几百毫秒的时间 。
info stats中的latest_fork_usec,可以看到最近一次form的时长 。
redis单机QPS一般在几万,fork可能一下子就会拖慢几万条操作的请求时长,从几毫秒变成1秒 。

优化思路:
fork耗时跟redis主进程的内存有关系,一般控制redis的内存在10GB以内,slave -> master,全量复制。

2. AOF的阻塞问题

redis将数据写入AOF缓冲区,单独开一个现场做fsync操作,每秒一次 ,但是redis主线程会检查两次fsync的时间,如果距离上次fsync时间超过了2秒,那么写请求就会阻塞 。everysec,最多丢失2秒的数据,一旦fsync超过2秒的延时,整个redis就被拖慢。

优化思路:
优化硬盘写入速度,建议采用SSD,不要用普通的机械硬盘,SSD,大幅度提升磁盘读写的速度

3. 主从复制延迟问题

主从复制可能会超时严重,这个时候需要良好的监控和报警机制 。
info replication中,可以看到master和slave复制的offset,做一个差值就可以看到对应的延迟量 。
如果延迟过多,那么就进行报警。

4. 主从复制风暴问题

如果一下子让多个slave从master去执行全量复制,一份大的rdb同时发送到多个slave,会导致网络带宽被严重占用 。
如果一个master真的要挂载多个slave,那尽量用树状结构,不要用星型结构。

5. vm.overcommit_memory 配置

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

6. swappiness

cat /proc/version,查看linux内核版本。
如果linux内核版本<3.5,那么swappiness设置为0,这样系统宁愿swap也不会oom killer(杀掉进程);
如果linux内核版本>=3.5,那么swappiness设置为1,这样系统宁愿swap也不会oom killer。
保证redis不会被杀掉 。

cat /proc/sys/vm/swappiness 
echo 0 > /proc/sys/vm/swappiness 
echo vm.swappiness=0 >> /etc/sysctl.conf 

7. 设置最大打开文件句柄

单个进程最多允许打开的文件句柄数(包括socket连接数)是有限制的,当大于这个系统限制时,程序会抛出大量的无法打开文件的报错。

# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
pending signals                 (-i) 515235
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 515235
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

其中open files表示的是单个进程最多允许打开的文件句柄数(soket连接数也算在内),默认值是1024。对于一般的程序来说,这个值是足够的,但是对于很多需要打开大量文件或者大量socket连接的程序来说,这个值就不够了。

设置每个进程的最大打开数,非root用户只能越设置越小,不能越设置越大

// 切换到root
sudo su - 
ulimit -n 10240 10240 

任何用户对ulimit -n的修改只在当前环境有效,退出后失效,重新登录新来后,ulimit -n由limits.conf决定。

可以使用如下命令:

echo fs.file-max=6553560 >> /etc/sysctl.conf 
echo "* soft nofile 10240"  >> /etc/security/limits.conf 
echo "* hard nofile 10240"  >> /etc/security/limits.conf 

修改之后,不需重启服务器,只需退出当前ssh远程连接,重新登录之后重启相关程序即可生效。

8. tcp backlog

cat /proc/sys/net/core/somaxconn
echo net.core.somaxconn=511 >> /etc/sysctl.conf

注意以上修改/etc/sysctl.conf,可以执行如下命令生效:

sudo sysctl -p

「真诚赞赏,手留余香」

请我喝杯咖啡?

使用微信扫描二维码完成支付

相关文章