这个坑值得记一笔。用 Memcached 1.6 缓存长 prompt 的渲染结果,单条 1.2MB,set 返回 SERVER_ERROR object too large for cache,客户端吞掉异常继续走,接口每次都回源,P99 从 400 毫秒涨到 3 秒。
刚开始盯着「压缩阈值设得比 1MB 还高,没触发压缩」,折腾了半个多小时,排掉了。
排查方向其实有限,先把可能性排一排。Memcached 单 item 上限 1MB,超过直接拒绝;客户端没检查 set 的返回值;用了文本协议,value 里的换行被截断。
上来先看实例的 item 大小限制
echo 'stats settings' | nc 127.0.0.1 11211 | grep -i item_size
再往下启动参数调大上限并重启
memcached -m 2048 -I 4m -u memcache
接着开启压缩并确认压缩后的长度
python -c "import zlib;b=b'x'*1200000;print(len(zlib.compress(b,6)))"
末了写入大 value 后读回比对长度
python -c "from pymemcache.client.base import Client;c=Client(('127.0.0.1',11211));print(c.set('k',b'x'*1200000))"
改之前我把相关日志按时间截了一段存着,事后对时间线用得上。
改完先别撤,确认这几项。1.2MB 的 value 能写入并原样读回,长度与写入一致,接口命中缓存后 P99 回到 400 毫秒以内。
Memcached 的单 item 上限是硬限制,调大要改启动参数且所有节点一致;更大的对象应该拆分或换 Redis,不要在客户端静默忽略 set 失败。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
