标题: 记一次 Redis 故障根因分析 分类: 工具 创建: 2024-01-12 10:56 修改: 链接: http://0x2531.tech/tools/202401121056.txt -------------------------------------------------------------------------------- 有天在工作群里,看到研发同事反馈 Redis 缓存过期后未销毁依然能 get 的问题。我不是 DBA,也没有 Redis 运维经验,只是轻度 Redis 使用者。但看着问题迟迟得不到解决,加之当时得空,想着不懂可以问 ChatGPT,于是便尝试分析下。 本文用到 redis-cli 工具的命令有: set --- 设置缓存,及有效期 get --- 获取缓存 ttl --- 获取缓存剩余时间(time to live) info stats --- 查看 Redis 实例统计信息 config get * --- 查看 Redis 实例配置信息 1、问题描述 通过 ttl 命令获取缓存有效期,一直返回 0,且通过 get 命令能正常获取到键值。 localhost:6380> ttl c3b2be1df4f65007dc17826121a15ad877001e07 (integer) 0 localhost:6380> ttl c3b2be1df4f65007dc17826121a15ad877001e07 (integer) 0 localhost:6380> get c3b2be1df4f65007dc17826121a15ad877001e07 "{\"uid\":\"100\",\"phone\":\"13912345678\"}" 2、问题诊断 执行 ttl 命令返回 0,表示缓存已过期,但键尚未清理。可能是该键被重置、清理策略失效或其它原因。没什么 想法,看下统计信息吧。 localhost:6380> info stats # Stats ... sync_partial_ok:0 sync_partial_err:0 expired_keys:0 evicted_keys:0 keyspace_hits:165504946 keyspace_misses:5073142741 ... 看到 expired_keys 和 evicted_keys 两个字段都为 0,表明 Redis 自启动起没有 1 个键过期被清理, 很可能是清理策略失效了。 此时,还是一头雾水。问下 ChatGPT 吧,提到可以查看配置信息。 localhost:6380> config get * 1) "dbfilename" 2) "dump.rdb" 3) "requirepass" 4) "" ... 125) "slaveof" 126) "192.168.0.1 6380" ... 注意到 slaveof 配置项,表明当前 Redis 实例是 192.168.0.1 的从库。好像有点头绪了,是不是往从库写 缓存,到期后不会自动删除呢?做个简单的实验验证下: localhost:6380> localhost:6380> get foobarbaz (nil) localhost:6380> localhost:6380> set foobarbaz "test" EX 10 OK localhost:6380> get foobarbaz "test" localhost:6380> ttl foobarbaz (integer) 4 localhost:6380> ttl foobarbaz (integer) 0 localhost:6380> ttl foobarbaz (integer) 0 localhost:6380> get foobarbaz "test" localhost:6380> get foobarbaz "test" 实验结果证明了假设是正确的。至此,缓存不过期的原因找到了。业务代码连的是 Redis 从库(从域名看是主 库...),然后设置缓存,自然永远不会过期。 3、问题处理 知道了问题根因后,处理方案就一目了然了。重新配置 Redis,将从库切换成主库就,然后重启 Redis 就可以 了。这步就交给 DBA 处理了。 4、反思 在大模型时代,学习成本直线下降。遇到未知领域,通过大模型的智慧,能很快获取基本认识。走出第一步,可能 是最重要的。这个大模型帮不了你,你自己需要首先克服畏难情绪。一旦走出第一步,事情就成功了一半。