Redis 故障排查

目录

一、Redis 日志设置

二、Redis 的几个重要健康指标

三、验证/修复RDB和AOF持久化文件

四、案例实战分析

要进行 Redis 的故障定位,一般通过分析 Redis 日志应用日志Redis 的监控信息来定位相关问题。

一、Redis 日志设置


【1】日志文件:Redis 默认日志在控制台打印,启动时即可看到对应日志打印到控制台上。建议修改 redis.config 的默认配置:[logfile ""],为其指定记录日志的文件[logfile "/usr/redis/log/redis.log"]。重启项目发现启动日志已经从控制台转到日志文件中了。
【2】日志级别:Redis 日志分为4个级别:debug、verbose、notice、warning 默认为 notice(生产一般使用此模式)

debug:会打印出很多信息,适用于开发和测试阶段
verbose(冗长的):包含很多不太有用的信息,但比debug要清爽一些
notice:适用于生产模式
warning:警告信息

【3】日志问题排查 :①、当 Redis 出现问题时,想通过 Redis 日志定位问题时,首先应查看 Redis 文件,确定日志的具体位置。②、分析日志内容,根据日志的具体内容,分析、定位问题。

二、Redis 的几个重要健康指标


【0】慢日志:①、通过命令[slowlog get]得到 Redis 执行的 slowlog 集合,理想情况下slowlog 集合应该为空即没有任何慢日志。②、若发现有慢命令,则应该逐个分析是否正常,是否需要优化。
【1】存活情况:是最重要的健康指标,通过命令 PING 的响应是否为 PONG 来判断。
【2】连接数:①、连接的客户端数量,[redis-cli info Clients|grep connected_clients] 得到,这个值与使用 Redis 服务的连接池配置关系比较大,这个值如果很大,需要排查问题原因。②、另外还有一个拒绝连接数(rejected_connections)也需要关注,这个值理想状态是 0 。如果大于 0,说明创建的连接数大于 maxclients,需要排查原因。是 Redis 连接池配合不合理还是连接这个Redis 的服务过多。
【3】阻塞客户端数量:blocked_clients 通常是执行了 list 数据类型的 BLPOP 或者 BRPOP 命令引起的,可以通过[redis-cli info Clients|grep blocked_clients]得到,这个值最应该=0。
【4】使用内存峰值:①、监控 Redis 内存使用峰值,可以通过命令[config set maxmemory]设置允许使用的最大内存。②、为了防止发生 swap 导致 Redis 性能骤减,甚至由于使用内存超标导致系统kill,建议used_memory_peak(占用内存的峰值)的值与maxmemory 的值有个安全区间,例如1G。
【5】内存碎片率:①、mem_fragmentation_ratio = used_memory_rss/use_memory 当值大于1时,表示分配的内存超过实际使用的内存,数值越大[利用率不高],碎片率越严重。当这个值小于1时,表示发生了 swap(Swap分区在系统的物理内存不够用的时候,把物理内存中的一部分空间释放出来,以供当前运行的程序使用) ,既可用内存不足。
  ②、Redis4.0 有一个主要的特性就是优化内存碎片率问题(Memory de-fragmentation)。在redis.conf 配置文件中[ACTIVE DEFRAGMENTATION:碎片整理允许 Redis 压缩内存空间,从而回收内存。此特性默认是关闭的,可以通过命令CONFIG SET activedefrag yes 热启动这个特性]。
  ③、当内存使用量(use_memory)很小的时候,这个值参考价值不大。所以建议 used_memory 至少 1G 以上才考虑对内存碎片率进行监控。
【6】缓存命中率:①、keyspace_misses/keyspace_hits 这两个指标用来统计缓存的命中率,keyspace_misses值未命中次数,keyspace_hits 表示命令次数。keyspace_hits/(keyspace_misses+keyspace_hits) 就是缓存命中率。②、如果缓存命中率过低,那么要排查对缓存的用法是否有问题。
【7】OPS:instantaneous_pos_per_sec 表示缓存的OPS(operation per second 每秒操作次数)
【8】持久化:①、rdb_last_bgsave_status/aof_last_bgrewrite_status,即最近一次或者最后一次 RDB/AOF 持久化是否有问题,这两个值都应该时 “OK”。②、由于 Redis 持久化时会 fork 子进程,且 fork 是一个完全阻塞的过程,所以可以监控 fork 耗时即:latest_fork_usec,单位是微妙,如果这个值比较大会影响业务,甚至出现 timeout 。
【9】失效KEY:如果把 Redis 当缓存使用,那么建议所有的 key 都设置 expire 属性,通过命令 redis-cli info Keyspace 得到每个 db 中 key 的数量和设置了 expire属性的 key 的属性,且 expires(表示设置了超时时间的key个数) 需要等于 keys。

三、验证/修复RDB和AOF持久化文件


【1】redis-check-dump:目前无法修复出错的快照文件,因为快照文件本身进行了压缩。快照中的错误可能会导致剩余部分无法访问。将重要的快照进行多次备份,在后期的恢复中通过计算数据的 SHA1 散列和 SHA256 散列对内容进行验证。
【2】redis-check-aof:运行 redis-check-aof --fix程序对 aof 文件进行修复。扫描 aof 文件,找到第一个出错的命令,并且删除出错命令及后续所有命令。一般情况下,被删除的都是 aof 文件末尾的不完整命令。

四、案例实战分析


【1】案例一现象:生产系统刚开始运行阶段,系统稳定。但是运行了一段时间后,发现部分时间段系统接口响应变慢。查看客户端日志经常会出现如下错误:

redis.clients.jedis.exception.JedisConnectionException:java.net.SocketTimeoutException:Read time out

【问题定位】:执行 slowlog 查看慢查询日志,发现大量的 keys 命令操作,keys 命令在大量并发情况下性能非常差,生产环境,尽量避免使用 keys,接下来找出使用 keys 的代码做优化,直到 time out 问题解决。

【2】案例二现象:生产环境长时间的运行后,经常会有接口返回数据失败的情况,或者是从监控上发现数据库压力某一时间暴增。查看客户端日志发现如下错误:

redis.clients.jedis.exceptions.JedisConnectionException:Cloud not get a resource from the pool

【问题定位】:执行 client list 命令,发现大量的 client 的 idle 时间特别长。检查配置发现 timeout 和 tcp-keepalive(心跳检测) 均为启用(均为0),Redis 服务端没有有效的机制来确保服务端连接是否已经失效。当服务器与客户端网络发生闪断,导致tcp中断,这种情况下的 client 将会一直被 redis 服务端所持有,就会出现 idle(空闲)时间特长的 client 连接。解决办法:设置 timeout 和 tcp-keepalive 来清理失效的连接。

【3】案例三现象:Redis 突然间不能访问,返回如下错误:

redis.client.jedis.exception.JedisDataException:MISCONF Redis is configured to save RDB snapshots,
but is currently not able to persist on disk.Commands that may modify the data set are disabled.
Please check Redis logs for details about the error

【问题定位】:查看 redis 日志,发现如下错误:Cant save in background:fork:Cannot allocate memory Redis在保存内存的数据到磁盘时,为了防止主线程假死,会Fork 一个子进程来完成这个保存操作,这个Fork 的子进程需要分配与主进程相同的内存,这时候就相当于需要的内存翻倍了。如果这时候可用内存不足以分配需要的内存,将会导致Fork 子进程失败而无法将数据持久化到磁盘。修改Linux内核参数 vm.overcommit_memeory=1表示内核允许分配所有的物理内存,而不管当前的内存状态如何) 问题便可解决。

----如果喜欢,点个  红心♡  支持以下,谢谢----

你可能感兴趣的:(分布式缓存【Redis】)