gomemcache 是 go 生产环境接入 memcached 最稳妥的选择,但需设 timeout(默认 0)、key 必须纯 ascii、value 必须 []byte、get 后必须判空、多节点仅为轮询非集群。

gomemcache 是 Go 生产环境中接入 Memcached 最稳妥的选择,它轻量、无状态、连接自动复用,但直接裸用容易掉坑里。关键不是“能不能连上”,而是“连上了之后怎么不出错”。
memcache.New() 后必须立刻设 Timeout
memcache.Client 默认 Timeout 是 0,意味着无限等待——一次网络卡顿就会让整个 HTTP 请求挂死。这不是理论风险,是线上高频故障点。
- 创建 client 后第一件事就是赋值:
mc.Timeout = 100 * time.Millisecond - 不要依赖文档里写的“默认 1s”,源码里就是
0 - 如果你用的是连接池(比如多个地址传给
memcache.New()),每个节点都共享这个Timeout,没法单独设 - 超时太短(如
10ms)会导致正常抖动也被判失败;太长(如500ms)会拖慢整体响应——建议从100ms起调,配合监控看 P99 延迟再微调
key 和 value 的类型限制不是可选项,是硬约束
gomemcache 只认 []byte,不处理任何序列化逻辑。传 string 或 struct 进去,代码能跑,但读出来大概率是空或乱码。
- key 必须是纯 ASCII 字符串:不能含空格、制表符、
\x00等控制字符;含中文或 emoji 会静默失败(Set返回nilerror,但实际没存) - value 必须是
[]byte:推荐统一走json.Marshal写入,json.Unmarshal读出 - value 大小建议 ≤ 1MB:Memcached 服务端会截断超长数据,且不报错;现象是
item.Value长度变短,但程序照常往下跑
Get 返回 nil item 不等于出错,这是最常 panic 的地方
mc.Get("missing-key") 返回 item == nil 且 err == nil —— 这是协议设计,不是 bug。但很多人直接写 string(it.Value),一查不到就 panic。
- 每次 Get 后必须先判空:
if item == nil { /<em> 未命中 </em>/ } - 别用
err != nil当命中判断依据:只有网络错误、协议错误才带err,缓存未命中时err是nil - 封装一层
GetJSON(key string, v interface{}) error很值得:内部做判空 +json.Unmarshal,业务层只管填结构体
多节点配置不等于自动负载均衡或高可用
memcache.New("a:11211", "b:11211", "c:11211") 看似集群,其实只是客户端轮询——没有一致性哈希,没有故障剔除,节点宕机后请求仍会打过去,直到超时。
- 它本质是“failover list”,不是“cluster”:请求按顺序尝试每个地址,第一个能通的就用,后续请求仍可能打到已挂节点
- 没有内置重试机制:单次请求失败就返回,不会自动换节点重试
- 如果真需要高可用,得自己加健康检查 + 动态剔除逻辑,或者改用支持 SASL 和一致性哈希的定制 client(如
memcache的 fork 版本),但多数场景不如直接上 Redis
真正麻烦的从来不是连上 Memcached,而是那些不报错却悄悄失效的行为:key 里混了不可见字符、value 序列化漏了指针解引用、Get 后忘了判空、Timeout 没设……这些细节堆在一起,比连不上还难排查。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











