直接按用户id做缓存的核心是分、命、管:用user:{id}构建稳定键,cache-aside模式读写(查缓存→未命中查库并回填,写时删缓存),分层缓存(basic/chats等),结合分片路由提升扩展性。

直接按用户 ID 做缓存,核心是让每个用户的读请求尽量走缓存、避免穿透数据库,同时保证数据一致性、可扩展、不互相干扰。关键不在“存”,而在“怎么分、怎么命、怎么管”。
用用户 ID 构建唯一且稳定的缓存键
缓存键必须包含用户身份标识,且不能依赖易变字段(比如昵称、头像URL)。推荐做法:
- 统一使用 user:{id} 作为基础前缀,例如
user:12345;若需区分数据类型,加二级标识,如user:12345:profile、user:12345:chats - 确保
id是整型或稳定字符串(如 UUID 经过 CRC32 或 MurmurHash 转为固定长度整数),避免哈希冲突或分布不均 - 避免在键中拼接时间戳、随机数等动态值,否则失去复用性
采用 Cache-Aside 模式管理读写一致性
这是最常用也最可控的方案:应用层主动协调缓存与数据库,不依赖中间件自动同步。
- 读流程:先查
user:{id}:profile→ 命中则返回;未命中则查库 → 写入缓存(设 TTL,如 30 分钟)→ 返回 - 写流程:更新数据库后,**立即删除**对应缓存(如
DEL user:12345:profile),而非更新——避免并发写导致脏数据 - 对强一致性要求高的字段(如余额、状态),可搭配「逻辑删除+版本号」或「延迟双删」(先删缓存、再更新库、休眠后再删一次)
按业务维度分层缓存,避免大而全的单条缓存
一个用户的数据往往分散在多个业务域,全量缓存成本高、失效难。建议分层设计:
-
轻量元数据层:如头像、昵称、角色,缓存周期长(1–24 小时),用
user:{id}:basic -
高频变动层:如最近聊天记录、未读消息数,缓存周期短(5–30 分钟),用
user:{id}:chats,序列化为 JSON 或 MessagePack - 关联 ID 列表层:如“我关注的人”ID 列表,只缓存 ID 数组(轻量),再配合单条用户缓存批量加载,降低穿透压力
结合分库分片做缓存路由协同
当用户数据已按 user_id % 1024 分到不同物理库时,缓存也可做轻量路由协同:
- 缓存 key 仍用
user:{id}:xxx,但连接池可按 slot 分组(如 slot 0–255 → redis-cluster-1),提升本地性 - 扩容时,只需迁移部分 slot 的缓存数据(而非全量),配合映射配置热加载即可
- 不强制要求缓存与 DB 物理位置一致,但保持逻辑分片数量一致(如都用 1024 slot),便于运维对齐











