<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Redis on Zero Day Notes</title>
        <link>https://blog.5772447.xyz/tags/redis/</link>
        <description>Recent content in Redis on Zero Day Notes</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-CN</language>
        <lastBuildDate>Wed, 22 Feb 2023 15:30:00 +0000</lastBuildDate><atom:link href="https://blog.5772447.xyz/tags/redis/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>一次Redis内存溢出导致缓存服务全部失效的排查实录</title>
            <link>https://blog.5772447.xyz/posts/61346c4a/</link>
            <pubDate>Wed, 22 Feb 2023 15:30:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/61346c4a/</guid>
            <description>&lt;h2 id=&#34;问题背景&#34;&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;某业务大促活动开始后约 2 小时，监控告警系统收到大量告警：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;数据库（MySQL）慢查询数量骤增，P99 响应时间从 50ms 升至 8000ms&lt;/li&gt;&#xA;&lt;li&gt;部分 API 接口 5xx 错误率达到 15%&lt;/li&gt;&#xA;&lt;li&gt;Redis 实例的 &lt;code&gt;rejected_connections&lt;/code&gt; 计数器快速增长&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;业务团队紧急联系运维排查，此时活动已进入高峰期，影响用户体验，需要快速定位并修复。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;故障现象&#34;&gt;&lt;a href=&#34;#%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;故障现象&#xD;&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;Redis &lt;code&gt;INFO&lt;/code&gt; 命令返回 &lt;code&gt;used_memory&lt;/code&gt; 接近服务器总内存&lt;/li&gt;&#xA;&lt;li&gt;Redis 日志中出现大量 &lt;code&gt;OOM command not allowed when used memory &amp;gt; &#39;maxmemory&#39;&lt;/code&gt; 错误&lt;/li&gt;&#xA;&lt;li&gt;应用日志中 Redis 写操作报错：&lt;code&gt;COMMAND NOT ALLOWED When Used Memory &amp;gt; &#39;maxmemory&#39;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;MySQL 慢查询日志急剧增多，大量查询耗时 5-10 秒&lt;/li&gt;&#xA;&lt;li&gt;部分服务接口响应超时，用户请求报 504&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;排查过程&#34;&gt;&lt;a href=&#34;#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;排查过程&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;第一步确认-redis-状态&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%80%e6%ad%a5%e7%a1%ae%e8%ae%a4-redis-%e7%8a%b6%e6%80%81&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第一步：确认 Redis 状态&#xD;&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redis-cli -h redis-prod-01 -p &lt;span style=&#34;color:#ae81ff&#34;&gt;6379&lt;/span&gt; -a &amp;lt;password&amp;gt; INFO memory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;关键输出：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;used_memory:8388557312          # 约 8GB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;used_memory_human:7.81G&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;maxmemory:8589934592            # 8GB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;maxmemory_human:8.00G&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;maxmemory_policy:noeviction     # ⚠️ 不淘汰策略&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mem_fragmentation_ratio:1.23&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;Redis 已用内存 7.81GB，最大内存限制 8GB，使用率 97.7%，几乎满了。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;关键发现：&lt;code&gt;maxmemory_policy&lt;/code&gt; 为 &lt;code&gt;noeviction&lt;/code&gt;&lt;/strong&gt;，意味着当内存满时，Redis 不会主动淘汰任何键，而是直接拒绝所有写操作（包括 SET、HSET、LPUSH 等），返回 OOM 错误。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第二步分析内存占用&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e5%88%86%e6%9e%90%e5%86%85%e5%ad%98%e5%8d%a0%e7%94%a8&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第二步：分析内存占用&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;查看 Redis 内存使用详情：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redis-cli -h redis-prod-01 -p &lt;span style=&#34;color:#ae81ff&#34;&gt;6379&lt;/span&gt; -a &amp;lt;password&amp;gt; MEMORY DOCTOR&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;输出提示内存碎片率正常，但总体内存占用过高。&lt;/p&gt;&#xA;&lt;p&gt;使用 &lt;code&gt;DEBUG JMAP&lt;/code&gt; 或 &lt;code&gt;redis-rdb-tools&lt;/code&gt; 分析大 Key：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 扫描占用内存最多的 key（生产环境谨慎使用 KEYS，使用 SCAN 替代）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redis-cli -h redis-prod-01 -p &lt;span style=&#34;color:#ae81ff&#34;&gt;6379&lt;/span&gt; -a &amp;lt;password&amp;gt; --bigkeys&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;发现几个异常的大 Key：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Biggest string found so far &amp;#39;&amp;#34;product:detail:cache:all&amp;#34;&amp;#39; with 524288000 bytes  # 500MB！&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Biggest hash found so far &amp;#39;&amp;#34;user:session:hash&amp;#34;&amp;#39; with 1258291 fields&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Biggest list found so far &amp;#39;&amp;#34;activity:log:queue&amp;#34;&amp;#39; with 2847593 elements&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;product:detail:cache:all&lt;/code&gt;&lt;/strong&gt; 这个 Key 存储了 500MB 的数据，这是一个&amp;quot;全量商品缓存&amp;quot;，是某开发同学为了提高商品详情接口性能，将全部商品数据序列化后存入一个 Redis Key 中。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;activity:log:queue&lt;/code&gt;&lt;/strong&gt; 是一个活动日志队列，因为消费者处理不及，积压了将近 300 万条记录。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第三步追溯大-key-的产生原因&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%89%e6%ad%a5%e8%bf%bd%e6%ba%af%e5%a4%a7-key-%e7%9a%84%e4%ba%a7%e7%94%9f%e5%8e%9f%e5%9b%a0&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第三步：追溯大 Key 的产生原因&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;通过查看应用代码和 Redis 写入监控，发现：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;product:detail:cache:all&lt;/code&gt;：大促前夕，开发同学为了&amp;quot;预热缓存&amp;quot;，写了一个脚本把全量商品（约 5 万个商品，每个商品序列化后约 10KB）存入一个 String Key。这个 Key 在大促当天被反复覆盖写入（每次预热都覆盖一次），每次写入耗时 2-3 秒，本身就是一个隐患。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;activity:log:queue&lt;/code&gt;：活动期间消费者处理速度远低于生产速度，积压数百万条未处理的日志条目，占用了大量内存。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;第四步评估立即处理方案&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e5%9b%9b%e6%ad%a5%e8%af%84%e4%bc%b0%e7%ab%8b%e5%8d%b3%e5%a4%84%e7%90%86%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第四步：评估立即处理方案&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;此时有几个选项：&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;方案 A：调大 maxmemory&lt;/strong&gt;（临时方案）&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;风险：服务器本身可用内存只有 12GB，Redis 已用约 8GB，系统还有其他进程，不建议调太高&lt;/li&gt;&#xA;&lt;li&gt;可临时调至 10GB，争取时间清理大 Key&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;方案 B：修改 maxmemory_policy 为 allkeys-lru&lt;/strong&gt;（临时方案）&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;让 Redis 自动淘汰最近最少使用的 Key&lt;/li&gt;&#xA;&lt;li&gt;风险：可能淘汰到重要的缓存数据，但好过直接拒绝写入&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;方案 C：立即删除大 Key&lt;/strong&gt;（直接处理）&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;删除大 String Key，释放 500MB 空间&lt;/li&gt;&#xA;&lt;li&gt;清空或截断积压 List&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;综合评估后，选择&lt;strong&gt;先临时调整 maxmemory_policy，再清理大 Key，最后重新评估内存上限&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;解决方案&#34;&gt;&lt;a href=&#34;#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;解决方案&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;第一步临时修改淘汰策略不重启&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%80%e6%ad%a5%e4%b8%b4%e6%97%b6%e4%bf%ae%e6%94%b9%e6%b7%98%e6%b1%b0%e7%ad%96%e7%95%a5%e4%b8%8d%e9%87%8d%e5%90%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第一步：临时修改淘汰策略（不重启）&#xD;&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redis-cli -h redis-prod-01 -p &lt;span style=&#34;color:#ae81ff&#34;&gt;6379&lt;/span&gt; -a &amp;lt;password&amp;gt; CONFIG SET maxmemory-policy allkeys-lru&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;修改后，Redis 开始主动淘汰冷数据，写操作不再被拒绝，应用侧错误率立即下降。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第二步删除大-key避免直接-del防止阻塞&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e5%88%a0%e9%99%a4%e5%a4%a7-key%e9%81%bf%e5%85%8d%e7%9b%b4%e6%8e%a5-del%e9%98%b2%e6%ad%a2%e9%98%bb%e5%a1%9e&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第二步：删除大 Key（避免直接 DEL，防止阻塞）&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;直接 &lt;code&gt;DEL&lt;/code&gt; 一个 500MB 的 Key 会阻塞 Redis 主线程数秒。使用异步删除：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Redis 4.0+ 支持 UNLINK 命令（异步删除）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redis-cli -h redis-prod-01 -p &lt;span style=&#34;color:#ae81ff&#34;&gt;6379&lt;/span&gt; -a &amp;lt;password&amp;gt; UNLINK &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;product:detail:cache:all&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;UNLINK&lt;/code&gt; 命令将 Key 的删除操作交给后台线程，主线程几乎无阻塞。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第三步截断积压-list&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%89%e6%ad%a5%e6%88%aa%e6%96%ad%e7%a7%af%e5%8e%8b-list&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第三步：截断积压 List&#xD;&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 保留最新的 10000 条，其余丢弃（或者清空）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redis-cli -h redis-prod-01 -p &lt;span style=&#34;color:#ae81ff&#34;&gt;6379&lt;/span&gt; -a &amp;lt;password&amp;gt; LTRIM &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;activity:log:queue&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;9999&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h3 id=&#34;第四步修正商品缓存设计&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e5%9b%9b%e6%ad%a5%e4%bf%ae%e6%ad%a3%e5%95%86%e5%93%81%e7%bc%93%e5%ad%98%e8%ae%be%e8%ae%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第四步：修正商品缓存设计&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;与开发同学沟通，将&amp;quot;全量商品缓存&amp;quot;改为按商品 ID 分散存储：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;product:detail:{product_id}  →  单个商品数据（约 10KB/key）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;并设置合理的 TTL（如 1 小时），避免永不过期。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第五步修复消费者积压问题&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%94%e6%ad%a5%e4%bf%ae%e5%a4%8d%e6%b6%88%e8%b4%b9%e8%80%85%e7%a7%af%e5%8e%8b%e9%97%ae%e9%a2%98&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第五步：修复消费者积压问题&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;扩容消费者实例数量（从 2 个扩到 8 个），加速消耗积压队列。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;根因分析&#34;&gt;&lt;a href=&#34;#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根本原因：&lt;strong&gt;缓存设计不合理 + maxmemory 策略配置错误&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;将大量数据存入单个 Redis Key，是典型的大 Key 反模式，不仅占用大量内存，还会导致网络带宽和序列化/反序列化的额外开销。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;使用 &lt;code&gt;noeviction&lt;/code&gt; 策略对于缓存场景来说是错误选择——它适用于数据不能丢失的持久化场景（如队列），但对于普通缓存应改用 &lt;code&gt;allkeys-lru&lt;/code&gt; 或 &lt;code&gt;volatile-lru&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;没有预估大促期间的内存需求，也没有设置合理的内存告警阈值（应在 80% 时告警）。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;预防措施&#34;&gt;&lt;a href=&#34;#%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;预防措施&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;1. Redis 内存监控告警&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;在 80% 使用率时告警，90% 时紧急告警，不等到 OOM 再处理。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;2. 大 Key 定期扫描&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;通过 &lt;code&gt;redis-cli --bigkeys&lt;/code&gt; 或 &lt;code&gt;redis-rdb-tools&lt;/code&gt; 分析 RDB 文件，定期检查大 Key：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 分析 RDB 文件（离线分析，不影响线上）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rdb --command memory dump.rdb | sort -rn -k3 | head -20&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3. 禁止大 Key 设计规范&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;在代码规范中明确：单个 Redis Key 的 Value 大小不超过 1MB，List/Hash/Set 的元素数量不超过 5000。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;4. 缓存淘汰策略合理化&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;纯缓存场景统一使用 &lt;code&gt;allkeys-lru&lt;/code&gt;，结合 TTL 管理数据生命周期。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;5. 生产变更前做容量评估&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;大促类活动前，评估 Redis 内存峰值需求，提前扩容。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次事故表明，Redis 的配置和使用规范同样需要纳入代码审查流程。一个大 Key、一个错误的淘汰策略，在平时可能不显眼，但到了业务高峰期就会变成定时炸弹。&lt;/p&gt;&#xA;&lt;p&gt;对于 Redis 运维，除了关注可用性，还要重点关注&lt;strong&gt;大 Key、热 Key、内存使用率、慢查询&lt;/strong&gt;这四个维度，建立起常态化的监控和审计机制。&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
