不能直接用grep扫描appendonly.aof文件定位异常操作,因为AOF是RESP协议编码的流式结构,grep会误匹配长度字段(如$3\r\nSET中的SET),导致结果失真;应使用waoffle解析为可读命令流后再分析。

不能靠 cat 或 grep 直接扫 appendonly.aof 文件来定位异常操作——它不是普通文本日志,而是 RESP 协议编码的流式结构,grep SET 极可能匹配到长度字段(比如 $3\r\nSET 中的 SET 字符串),结果完全失真。
为什么直接 grep AOF 文件会误报?
AOF 文件每条命令由多行组成:*N 表示参数个数,$M 表示后续内容字节数,结尾固定为 \r\n。例如 SET user:1001 "abc" 实际存为:
*3\r\n$3\r\nSET\r\n$9\r\nuser:1001\r\n$5\r\n"abc"\r\n
这意味着:
-
grep FLUSHALL可能命中$8\r\nFLUSHALL,但也可能命中$12\r\nSOME_FLUSH_ALL_KEY这类键名 -
grep -a 'KEYS \*'会漏掉真实命令,因为 AOF 里是*2\r\n$4\r\nKEYS\r\n$1\r\n*,KEYS和*不在同一行 - 用
less手动翻页时,容易把$5\r\nvalue当成独立命令,误判为非法写入
用 waoffle 把 AOF 转成可读命令流
waoffle 是目前最可靠的离线解析器,它按 RESP 规则逐帧解析,不依赖 Redis 进程,也不会被截断或重写干扰。安装后执行:
waoffle appendonly.aof > commands.txt
输出就是干净的命令行,例如:
SELECT 0<br>SET user:1001 "original"<br>EXPIRE user:1001 3600<br>DEL user:1001
这时再用 grep 就真正可信了:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 查清空操作:
grep -E '^(FLUSHALL|FLUSHDB)$' commands.txt - 查高频写入:
awk '{print $1}' commands.txt | sort | uniq -c | sort -nr | head -10 - 查可疑键:
grep -E '^(SET|HSET|LPUSH)' commands.txt | grep '\.tmp|_backup|__test'
结合上下文定位误操作源头
AOF 本身不含时间戳,但异常操作往往有行为特征。不要孤立看某条命令,重点观察「前后三行」:
- 如果发现
DEL user:1001,立刻用grep -A2 -B2 "user:1001" commands.txt查前因后果——是否前面有GET user:1001+INCR user:1001:counter,说明是业务逻辑误删 - 遇到
EXPIRE或PEXPIREAT,注意它不会回溯原始过期时间,重放时是“按当前时间重设”,所以分析重点应是值变更链,而非时间点 - 若怀疑是脚本批量操作,搜
^MSET或^LPUSH后接大量参数的行,这类命令在waoffle输出中仍保持单行,易识别
修复前必须跑 redis-check-aof --check
waoffle 解析失败时默认静默退出,不报错。真正动手前,务必先确认 AOF 文件结构完整:
redis-check-aof --check appendonly.aof
输出类似:
AOF analyzed: size=2456789 bytes, ok_up_to=2456000 bytes, diff=789 bytes
如果 ok_up_to 明显小于文件大小,说明末尾有损坏或不完整命令——此时 waoffle 可能只解析出前半部分,你看到的“最后一条命令”根本不是真实的最后操作。
RESP 协议的脆弱性藏在细节里:少一个 \r\n、长度声明与实际不符,都会让整个解析链失效。别跳过校验这步。

















