Redis里怎么灵活玩转组合key,避免踩坑又高效用法分享
- 问答
- 2026-01-15 11:44:49
- 2
说到Redis,很多人刚开始用的时候,最喜欢的就是用简单的key,比如user:123来存用户信息,这没错,很简单直接,但业务一复杂,问题就来了,你想查“某个用户收藏了哪些文章?”或者“某个标签下最近三天有哪些新帖子?”,这时候,如果你只用单个key,要么得查全量数据在内存里自己过滤(慢且耗资源),要么就得维护一堆很难管理的key,这就是我们今天要聊的,怎么灵活地玩转组合key。
组合key的核心思想,其实不是把key的名字取得花里胡哨,而是利用Redis丰富的数据结构,把有关联的数据巧妙地组织在一起,目的就是为了让你能用最少的网络请求,最高效地查到想要的数据。
第一招:用Set(集合)搞定多对多关系
这个招数在社交场景里特别管用,用户和用户之间的关系,用户和兴趣标签之间的关系,根据Redis官方文档对Set数据结构的介绍,Set里的元素是唯一的、无序的,非常适合用来存储这种关系。
举个例子,你有两个用户,ID分别是1和2,用户1关注了用户2,你怎么存呢?你可以为每个用户创建两个Set类型的key:
user:1:followings-> 这个Set里存放的是用户1关注的所有人的ID,{2, 3, 5}user:2:followers-> 这个Set里存放的是关注用户2的所有人的ID,{1, 4}
你看,这样存储之后,查询就变得异常简单:
- 查“用户1关注了谁?”:直接
SMEMBERS user:1:followings,一步到位。 - 查“用户2被谁关注了?”:直接
SMEMBERS user:2:followers,也是一步到位。 - 甚至查“用户1和用户3的共同关注?”:直接用Set的交集命令
SINTER user:1:followings user:3:followings,Redis帮你算得好好的。
这种方法的好处是,关系维护和查询都非常快,完全是O(1)或者O(N)的复杂度(N是集合大小),避免了在应用层做复杂的循环和过滤。
第二招:用Sorted Set(有序集合)玩转排行榜和时间线
Sorted Set是Set的升级版,每个元素都带一个分数(score),这个分数太有用了,可以用来排序,根据Redis实战案例,这个结构是构建排行榜、延迟队列、时间线系统的神器。
做一个文章点赞排行榜,你可以创建一个Sorted Set类型的key,叫article:likes:rank。
- 键(key):
article:likes:rank - 值(member):文章ID
- 分数(score):这篇文章获得的点赞数
当有人给一篇文章点赞时,你就执行ZINCRBY article:likes:rank 1 文章ID,这个命令非常聪明,如果文章ID已经存在,就给它的分数加1;如果不存在,就创建它并设置分数为1,要查Top 10的文章?一句ZREVRANGE article:likes:rank 0 9 WITHSCORES就搞定了,效率极高。
再比如,做朋友圈的时间线,每个用户发一条状态,你可以这样做:
- 为每个用户维护一个Sorted Set,key叫
user:123:feed,member是状态ID,score是发布时间戳。 - 维护一个全局的Sorted Set,key叫
global:feed,同样存放所有状态ID和发布时间戳。
当用户A关注用户B后,可以把用户B最近的状态ID,合并(ZUNIONSTORE)到用户A的个人时间线Sorted Set里(实际实现会有更优化的方式,比如推拉结合),这样,用户查看朋友圈时,直接按score倒序从自己的时间线Sorted Set里取就行了,速度飞快。
第三招:用Hash(哈希)来分组管理属性
一个对象有很多属性,比如用户有姓名、年龄、城市等等,如果你用普通的String类型,每个属性存一个key(如user:123:name, user:123:age),那么取用户完整信息就要跑很多次网络请求,这叫“缓存原子性”问题,很亏。
这时候,Hash结构就派上用场了,根据Redis命令参考,Hash允许你在一个key里面存储多个字段(field)和值(value),你可以把整个用户信息存成一个Hash:
- key:
user:123 - 字段和值:
name "张三",age "30",city "北京"
这样,操作就高效多了:
- 取用户所有信息:
HGETALL user:123,一次网络往返就拿全了。 - 只更新用户年龄:
HSET user:123 age 31,只修改一个字段,不影响其他。 - 只获取用户名和城市:
HMGET user:123 name city,可以按需获取。
这种方法特别适合存储那些字段多、但可能不会每次都全部用到的对象,既保证了操作的原子性,又减少了网络开销。
避免踩坑的小提示
- 别让key太长:key的名字要有意义,但也别太长,比如
system:config:database:mysql:master:connection:pool:max_size这种,虽然清晰,但浪费内存,可以用缩写或者编码替代长单词。 - 警惕大key:一个Set里面有几百万个元素,或者一个Hash有几千个字段,这种叫“大key”,大key会导致操作变慢,甚至阻塞Redis,解决办法是拆分,比如按日期拆分
article:likes:20240521,或者按ID取模拆分到多个key里。 - TTL设置要小心:给你组合key设置过期时间时,要确保相关的key都有合理的过期策略,别用户信息过期了,他对应的关注列表还没过期,导致数据不一致。
- 命名要有规律:比如都用冒号分隔,形成一种命名空间。
user:123:profile,user:123:followers,这样在管理(比如用KEYS user:123:*模式匹配)或者清理时,会非常方便。
玩转Redis组合key,精髓在于“用数据结构表达数据关系”,Set管归属、Sorted Set管排序、Hash管对象,避开大key和长key的坑,根据你的查询需求去设计key的结构,而不是简单地把数据库表结构照搬过来,这样,你的Redis用起来就会既灵活又高效。

本文由瞿欣合于2026-01-15发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/81144.html
