本篇为Redis性能问题诊断系列的第四篇,也是末了一篇,紧张从运用程序、系统、做事器硬件及网络系统等层面上进行讲解,重点分享了哪些配置须要重点关注和调度优化,才能最大程度的发挥Redis的处理能力;
一、做事器预留足够内存,监控SWAP利用
Swap是操作系统层面行为,指当做事器内存不敷时,会将原来在内存中的一部分数据拿出放入磁盘,如果再次访问这部分数据就会相应很慢,由于磁盘的访问速率是远远不如内存的。
Redis作为内存数据库,有个知识一定要记住:所有的数据默认都是在内存中,不存在一部分在内存一部分在磁盘中的情形,除非被迫发生了SWAP。
解释:Redis在2.6版本之前有个VM【虚拟内存】特性,可以支持数据存放在内存和磁盘中,不过带来的性能颠簸影响太大,就被废弃了。但现在网上还有不少人在传抄干系VM特性的文章,太有误导性!
官方VM废弃解释:https://redis.io/docs/reference/internals/internals-vm/
可以通过以下办法来查看 Redis 进程是否利用到了 Swap:
1.获取redis对应的进程id
shell> redis-cli info | grep process_id
2.查看 Swap 利用情形
shell>cat /proc/$pid/smaps | egrep '^(Swap|Size)'#输出结果如下:Size: 1492 kBSwap: 0 kBSize: 32 kBSwap: 0 kBSize: 2196 kBSwap: 0 kBSize: 2048 kBSwap: 0 kBSize: 4 kBSwap: 0 kBSize: 1576 kB
上述中size代表Redis进程占用的一块内存空间大小,并对应一个Swap。Swap后的数字表示该内存空间有多少已经被换到磁盘上了,如果两者相等,则代表这块内存空间的数据全都被换到了上了。针对利用swap的办理方案可以参考如下:
提高Redis所在做事器的内存并预留可用内存,建议剩余可用内存至少保留20%以上;Redis单独支配或降落单机支配实例数量,反面其他运用程序稠浊支配,避免多做事争用内存导致Redis数据被swap到磁盘上。平时对Redis所在做事器的剩余可用内存及Swap 利用情形进行监控,在内存不敷或利用到 Swap 时报警出来,及时干预处理。
二、.利用万兆网卡,避免网络带宽打满
Redis 的高性能,除了数据都在内存之外,就在于网络 IO 了,如果网络存在瓶颈,那么也会严重影响 Redis 的性能。网络带宽过载的情形下,比如带宽被打满,那么做事器在 TCP 层和网络层就会涌现数据包发送延迟、丢包等情形。如果确实涌现这种情形,我们须要及时核对缘故原由,紧张有以下几个:
某个Redis做事访问量过大,可能QPS高再叠加操作的Key过大,导致网络满载;所在做事器网卡上限过小,如千兆网卡或者虚拟机限速200MB等;做事器网卡/网线/驱动等问题,导致万兆的网卡降频为千兆或者被限流。查看网卡速率:ethtool eth0
针对网络过载可以采取以下方案来办理:
降落单机支配Redis实例个数,打散重度利用网络带宽的Redis做事到多台做事器;对Redis做事利用的网络带宽进行监控,可以关注性能指标:instantaneous_input_kbps、instantaneous_output_kbps利用万兆网卡的做事器,并添加对带宽上限【当心网卡从万兆降为千兆】、网络带宽利用、丢包情形的监控;遵守Redis利用规范,比如掌握写入Redis中的VALUE大小、限定利用smembers或hgetall等操作的凑集成员个数等。三、根据场景选择是否利用SSD磁盘
大家要根据自己的实际场景判断,比如利用单节点且用于缓存做事的环境,就不须要利用SSD磁盘。但是如果希望利用Redis的持久化能力来担保数据安全,那么磁盘IO能力就不得不重视了。这里对付Redis的持久化不做详细先容,详细可以参考上篇文章。
Redis中对IO比较敏感的操作紧张有下面几类:
a.AOF持久化,干系磁盘操作有:AOF命令落盘、AOF文件重写;
b.RDB持久化,干系磁盘操作有:主从复制主节点RDB天生快照、从节点加载RDB文件、备份触发RDB快照、配置触发自动RDB快照
上面列出的都会严重依赖磁盘IO能力,特殊是单机支配多Redis实例的情形,如果磁盘IO能力一样平常,那么就会严重影响Redis的性能。
四、系统参数配置
1.内存分配策略参数vm.overcommit_memory
Redis启动给出Warning提示:
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.
这里首先解答下什么是Overcommit?Linux对大部分申请内存的要求都回答"yes",以便能跑更多更大占用内存的程序。由于申请内存后,并不会立时利用内存。这种技能叫做Overcommit。当linux创造内存不敷时,会发生OOM killer(OOM=out-of-memory)。它会选择杀去世一些进程(用户态进程,不是内核线程),以便开释内存。
overcommit_memory的几个紧张值得解释:
0:表⽰内核将检讨是否有⾜够的可⽤内存供应⽤进程使⽤;如果有⾜够的可⽤内存,内存申请许可;否则,内存申请失落败,并把缺点返回给应⽤进程;
1: 表⽰内核许可分配所有的物理内存,⽽不管当前的内存状态如何;
2: 表⽰内核许可分配超过所有物理内存和交流空间总和的内存。
这里建议调度为1,干系调度办法:
永久生效:编辑vim /etc/sysctl.conf ,改vm.overcommit_memory=1,然后sysctl -p 使配置文件生效
临时生效:
echo 1 > /proc/sys/vm/overcommit_memory
上述日志中的Background save代表的是bgsave和bgrewriteaof, 如果当前可用内存不敷, 操作系统该当如何处理fork操作呢?
如果vm.overcommit_memory=0, 代表如果没有可用内存, 就申请内存失落败, 对应到Redis便是实行fork失落败, 在Redis的日志会涌现:Cannot allocate memoryRedis建议把这个值设置为1, 是为了让fork操作能够在低内存下也实行成功。
2.操作系统内存大页参数配置
Redis启动给出Warning提示:
WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
意思是:你的Redis所在做事器当前利用的是内存大页机制,可能导致Redis访问延迟和内存利用问题。
那什么是内存大页呢?
运用程序向操作系统申请内存空间时,是按内存页为单位进行申请的,默认大小是4KB。不过Linux从 2.6.38内核版本开始,支持了内存大页机制,可以许可向操作系统一次申请 2MB 大小的内存。
由于申请的内存单位变大,也意味着申请耗时相对变长。那对付 Redis做事会有什么影响呢?
当 Redis 在实行后台 RDB 和 AOF rewrite 时,采取 fork 子进程的办法来处理。但主进程 fork 子进程后,此时的主进程依旧是可以吸收写要求的,而进来的写要求,会采取 Copy On Write(写时复制)的办法操作内存数据。也便是说,主进程一旦有数据须要修正,Redis 并不会直接修正现有内存中的数据,而是先将这块内存数据拷贝出来,再修正这块新内存的数据,这便是所谓的「写时复制」。
写时复制可以理解为:须要发生写操作哪个Key,就须要先拷贝这个Key,然后再修正。这里把稳,主进程在修正拷贝内存数据时,这个阶段就涉及到新内存的申请。如果此时操作系统开启了内存大页,那么在此期间,运用程序即便只修正 10B 的数据,Redis 在申请内存时也会以 2MB 为单位向操作系统申请,申请内存的耗时变长,进而导致每个写要求的延迟增加,影响到 Redis 性能。
所以为了避免过多的内存申请,我们须要关闭内存大页机制:
cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
如果输出选项是 always,就表示目前开启了内存大页机制,我们须要关掉它:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
实在,操作系统供应的内存大页机制,其上风是可以在一定程序上降落运用程序申请内存的次数。
比如针对大数据、工具存储干系的做事来说可能会更好,但是对付 Redis 这种对性能和延迟极其敏感的数据库来说,我们希望 Redis 在每次申请内存时,耗时只管即便短,建议关闭这个参数。
五、其他影响访问Redis的性能的成分
1.运用程序配置不合理
a.应配置合理的连接数等干系参数,比如jedis,默认MaxActive最大连接数只有8个,在高QPS时就会涌现无法获取新连接的提示:redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool … Caused by: java.util.NoSuchElementException: Timeout waiting for idle object at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)
b.驱动版本过低。低版本的Driver连接高版本Redis,除了无法利用最新的特性外,还会常常涌现连接不开释、内存透露、访问缓慢等问题。
2.利用连接池配置
避免利用短连接模式.特殊是利用PHP的运用,频繁的连接创建与销毁,在高QPS访问时网络开销巨大;
3.CPU绑核及主频影响
Redis是单线程模型处理处理用户需求,那么处理的吞吐、效率就会极度依赖CPU的处理能力,以是选型CPU时,如果支配的Redis平时QPS较高,可以采购主频高些的CPU.
其余现在的CPU都是多核处理,为了提高做事性能,降落运用程序在多个 CPU 核心之间的高下文切换带来的性能损耗,常日采取的方案是进程绑定 CPU 的办法提高性能。
但是Redis的绑核操作过于繁芜,对付单机多实例的管理寻衅过高,再加上Redis 的性能已经足够精良,不建议绑定 CPU来处理,这里也不做深入解释。
末了总结:
本篇为Redis性能诊断的完结篇,通过总结常见的可能导致访问相应延迟、乃至壅塞的问题的各种场景,以及如何定位及剖析针对性地供应理解决方案。但是由于篇幅限定,关于 Redis 的很多细节也无法全部展开,后续也会对Redis利用的各种技巧、架构及内部的事情事理深入分享,欢迎保持关注。
如果这篇文章对你有帮助,还请帮忙点赞、转发 一下,你的支持会勉励我们输出更多高质量的文章,非常感谢!
如果你还想看更多优质文章,欢迎关注我的公号「数据库架构师」,提升数据库技能,一起助力职业发展。
推举阅读
Redis变慢?深入浅出Redis性能诊断系列文章(三)
Redis变慢?深入浅出Redis性能诊断系列文章(二)
Redis变慢?深入浅出Redis性能诊断系列文章(一)