redis 性能优化三

本文讨论了如何通过优化Redis的文件系统调度(writevsfsync)、调整AOF配置、管理内存swap以及关闭大内存页机制来提升Redis的性能。还强调了监控过期keys和内存使用情况的重要性,以及针对bigkeys的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

如果Redis 没有执行大量的慢查询,同时也没有删除大量的过期的keys,那么我们该怎么办呢?那么我们是不是就应该关注影响性能的其他机制了,也就是文件系统和操作系统了。

Redis 会把数据持久化到磁盘,这个过程依赖文件系统来完成,文件系统把数据写回磁盘的机制,会直接影响到Redis 持久化效率。而且,在持久化的过程中,Redis 也还在接收其他请求,持久化的效率高低又会影响到Redis 处理请求的性能。

Redis 是内存数据库,内存操作非常频繁,所以,操作系统的内存机制会直接影响到Redis 的处理效率。比如说,如果Redis 的内存不够用了,操作系统会启动swap 机制,这就拖慢了Redis。

下面我将从这两个方面讲解:

Redis 持久化优化

首先我们要明白文件系统有两种系统调度,是write 和 fsync 。这两种有什么区别:

write: 只要把日志记录写到内核缓冲区,就可以返回了,并不需要等待日志实际写回到磁盘

fsync: 需要把日志记录写回到磁盘后才能返回,时间较长。

在日志文件里,关于aof 的配置项,appendfsync 有 no,everysec,always。no 就是文件系统的write 调度,文件系统周期性把日志写回磁盘。剩下的都是fsync 将日志写回磁盘,everysec、always 不同的是 everysec 是由后台子线程完成fsync的操作,always 使用主线程去操作

aof 日志,避免日志文件增大,会进行aof 重写,缩小aof 日志文件,aof 重写是子线程异步执行的。

如果aof 重写压力大,会对磁盘进行大量IO操作,fsync 需要等到数据落盘才能返回,就会导致fsync 被阻塞。fsnyc 可能由子线程完成,但是主线程会监控fsync 的执行速度。如果上一次fsync 还没有写完,被主线程监控发现了,主线程就会阻塞,redis 会变慢了。

对于这个点的优化,要根据业务考虑,如果只是当缓冲用,数据丢了,可以从数据库获取,那么 appendfsync 可以设置no, everysec

还有一个配置 no-appendfsync-on-rewrite yes 默认是no 如果 yes 就是表示aof 重写,不进行fsync 操作,也就是说Redis 实例把写命令写到内存后,不调用后台线程进行 fsync 操作,就可以直接返回了。当然,如果此时实例发生宕机,就会导致数据丢失。‘

以上根据业务配置,我们也可以升级硬件,比如采用高速的固态硬盘作为aof 日志的写入设备。

操作系统的swap

什么是操作系统的swap?

内存 swap 是操作系统里将内存数据在内存和磁盘间来回换入和换出的机制,涉及到磁盘的读写,所以,一旦触发 swap,无论是被换入数据的进程,还是被换出数据的进程,其性能都会受到慢速磁盘读写的影响。

Redis 高性能的原因就是数据直接写在内存里,如果给Redis 的内存不足,并且操作系统开启了swap。就会把一部分数据写到磁盘,导致Redis性能下降,数据的读写都是在主线程完成的,此时主线程读写磁盘,增加Redis 的响应时间。

这种情况一般是这样产生的:

  1. Redis 实例使用了大量的内存,导致物理内存不足

  2. Redis 实例和其他进行运行一台机器,其他进行大量文件读写。文件读写本身消耗内存,这会导致分配给 Redis 实例的内存量变少,进而触发 Redis 发生 swap

这种情况,增加内存或者用机器,redis 实例服务器没有其他的外部进程,除了系统内部的进程。

操作系统本身会在后台记录每个进程的 swap 使用情况,可以用下列命令查看进程的swap使用情况:

  1. ./redis-cli info | grep process_id 查看redis 进程id

  2. cd /proc/5332. 进入 Redis 所在机器的 /proc 目录下的该进程目录中:

  3. cat smaps | egrep '^(Swap|Size)' 查看该 Redis 进程的使用情况:

    $cat smaps | egrep '^(Swap|Size)'
    Size: 54 kB
    Swap: 0 kB
    Size: 10 kB
    Swap: 10 kB
    Size: 4 kB
    Swap: 0 kB
    Size: 462044 kB
    Swap: 462008 kB

    上面解释如下:

    每一行 Size 表示的是 Redis 实例所用的一块内存大小,而 Size 下方的 Swap 和它相对应,表示这块 Size 大小的内存区域有多少已经被换出到磁盘上了。如果这两个值相等,就表示这块内存区域已经完全被换出到磁盘了。

    发现 Swap ,就需要增加机器内存。如果是集群,需要增加集群实例。

大内存页的优化

Linux 内核从 2.6.38 开始支持内存大页机制,该机制支持 2MB 大小的内存页分配,而常规的内存页分配是按 4KB 的粒度来执行的。

很多人认为大内存页可以避免内存的分配次数。确实是这样的,但是redis 有个cow 机制,数据修改后,会申请一块新的内存,并对数据拷贝,如果内存大的话需要拷贝大的内存。你可以看到,当客户端请求修改或新写入数据较多时,内存大页机制将导致大量的拷贝,这就会影响 Redis 正常的访存操作,最终导致性能变慢。

那么我们应该关闭内存大页机制

cat /sys/kernel/mm/transparent_hugepage/enabled

如果是always 就是启动了,never 就是没有启动,可以用下面去修改

echo never /sys/kernel/mm/transparent_hugepage/enabled

好了,写到这里已经很多了,这个需要不断总结,需要对redis 进行监控:

监控大量的key 是否集中过期:

./redis-cli info | grep expired_keys 数据很大报警

监控因为超过最大内存,被淘汰的keys

./redis-cli info | grep evicted_keys

解决方案,改变淘汰策略,随机比较快,还有集群扩容,分担压力

./redis-cli info | grep latest_fork_usec 监控这个值,有可能RDB和AOF 重写期间,实例占用内存大,fork拷贝内存页表越久

解决方案:实例小,部署在物理机器上,情况关闭aof,合理配置repl-backlog和slave client-output-buffer-limit,避免主从全量同步

bigkeys 的监控

redis-cli -h $host -p $port --bigkeys 扫描bigkeys

解决方案,bigkeys 分片存储,Redis 4.0+可开启lazy-free机制 可以异步删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值