必须用一致性哈希,因取模分片节点增减时约75%的key映射失效,引发缓存雪崩;一致性哈希配合100~200个虚拟节点可将重映射压至1%以内,且需确保哈希函数、replicas数、节点标识格式完全一致。

Go语言实现基于分片的分布式缓存访问策略,核心在于让数据“找得到、分得匀、切得稳”,而不是简单把key扔给某个节点。关键不在写多少代码,而在选对分片逻辑和兜住边界问题。
必须用一致性哈希,别碰取模分片
直接 hash(key) % len(nodes) 看似简单,但节点从3扩到4时,约75%的key归属会变,缓存集体失效,数据库瞬间被打爆——这叫缓存雪崩,不是理论风险,是线上高频故障。
- 一致性哈希把节点和key都映射到同一个0~2³²−1哈希环上,增减节点只影响环上相邻一小段区间
- 配合虚拟节点(replicas设100~200),重映射比例可压到1%以内
- Go标准库不提供现成ConsistentHash,但自己实现结构体不到50行,字段至少含:哈希函数、虚拟节点数、升序keys切片、虚拟节点→真实节点映射表
- 每次Add节点后必须调 sort.Ints(m.keys),否则 sort.Search 查找永远返回第一个节点
分片路由要防panic、防错位
Get(key)看着一行,实操中三个点最容易出错:
- 没对查找索引做取模就直访问 m.keys[idx] → panic: index out of range
- sort.Search 条件写成 m.keys[i] > h 而非 >= h → 找不到相等值时返回错误位置
- 哈希函数别用sha256,推荐 crc32.ChecksumIEEE 或 fnv.New32a(),轻量且分布更均匀
客户端连接必须匹配部署模式
生产环境几乎不用单节点Redis,硬套 redis.NewClient 是最大陷阱:
立即学习“go语言免费学习笔记(深入)”;
- 哨兵模式用 redis.NewFailoverClient,必须传 MasterName 和全部哨兵地址,漏一个就初始化失败
- 集群模式用 redis.NewClusterClient,节点列表填2–3个即可自动发现其余节点,但首次任一节点连不上整个client就panic,需外层加err判断
- 所有连接务必设 Timeout: 3 * time.Second 和 MaxRetries: 2,否则网络抖动时请求卡死在ctx.Done()
缓存读写要带兜底和扰动
分片只是路由,真正影响稳定的是读写细节:
- 防穿透:查不到时,Set(ctx, key, "null", 1*time.Minute) 占位,业务层判 val == "null" 后跳过DB
- 防雪崩:TTL别写死,用 baseTTL + jitter,jitter用 rand.New(rand.NewSource(time.Now().UnixNano())) 避免重启后扰动重复
- 结构体序列化按场景选:纯Go服务用 gob(快40%、省内存);多语言或对外API必须用 json,且显式加 json:"field_name,omitempty"


















