当前位置:首页 > 问答 > 正文

Redis里集合和哈希那些概念,感觉得重新理一理才能明白到底啥意思

你感觉Redis里的集合和哈希需要重新理一理,这个感觉太对了,它们名字听起来简单,但刚接触时,很容易和编程语言里的概念,或者彼此之间搞混,咱们就抛开那些复杂的术语,用最直白的方式把它们捋清楚。

来源参考:主要基于Redis官方文档对数据结构的基本定义,并结合常见的理解误区进行解释。

先打个比方:超市购物

想象一下你去超市买东西,这个场景能帮你很好地理解这两个概念。

  • 你的购物车整体,可以看作一个 Redis 键,这个键里面放着你这次购物所有的商品。
  • 集合 就像是你扔进购物车里的一堆水果,比如你拿了一个苹果、一个香蕉、一个橙子,它的核心特点是:独一无二,顺序无关,你不会在意先拿苹果还是先拿香蕉,购物车里最终只有一个苹果、一个香蕉、一个橙子,就算你再拿一个苹果放进去,购物车里的苹果也不会变成两个,因为它已经存在了,集合就是干这个的,它保证每个成员都是唯一的,并且不按你放进去的顺序存储。
  • 哈希 则像是购物车里的一件“组合商品”,比如一箱牛奶,这箱牛奶本身是一个整体(对应Redis的一个键),但它的内部又有自己的属性:品牌”是蒙牛,“口味”是纯牛奶,“生产日期”是2023年10月,“容量”是250ml,哈希就是用来存这种“一个键对应多个字段-值对”的东西,它非常适合表示一个对象。

有了这个大概印象,我们再深入一点。

集合:一个装独特元素的袋子

集合的核心就两点:唯一性无序性

  1. 唯一性:这是它最根本的特性,你要统计一篇文章的所有独特标签(去重后的),你可以用一个集合叫 article:1001:tags,然后不断往里面加标签:sadd article:1001:tags Redis 数据库 缓存,无论你加多少次“Redis”,这个集合里最终只有一个“Redis”,这非常适合做去重操作。

  2. 无序性:你往集合里添加元素的顺序,和你用命令查看时的顺序,很可能是不一样的,Redis为了效率,自己决定怎么存,你不能说“给我集合里的第二个元素”,因为没有“第二个”这个概念。

  3. 强大的集合运算:这是集合的杀手锏,回到超市的例子,假设你有两个购物车(两个集合):

    • 集合A(你的购物车):{苹果, 牛奶, 面包}
    • 集合B(你朋友的购物车):{香蕉, 牛奶, 鸡蛋} Redis可以让你轻松求出:
    • 交集:两个购物车都有的东西 -> SINTER 命令 -> 结果:{牛奶}
    • 并集:你们两个购物车所有不重复的东西 -> SUNION 命令 -> 结果:{苹果, 牛奶, 面包, 香蕉, 鸡蛋}
    • 差集:你的购物车里有,但你朋友车里没有的东西 -> SDIFF 命令 -> 结果:{苹果, 面包} 这个功能在社交应用中非常有用,比如计算共同好友、推荐可能认识的人等。

当你需要存一堆不允许重复的值,并且未来可能要做一些“找共同点”、“找不同点”的操作时,就用集合。

哈希:一个带标签的档案袋

哈希的核心是结构化,它把一个键的值,从单一的一个字符串,变成了一个由多个“字段”和“值”组成的映射表。

  1. 表示对象:这是哈希最典型的用法,比如要存一个用户信息,如果你用普通的键值对,可能会这样:

    • user:1001:name -> “张三”
    • user:1001:age -> “28”
    • user:1001:city -> “北京” 这需要维护很多个键,而用哈希,一个键就搞定了:
    • 键名:user:1001
    • 值(一个哈希结构):
      • 字段 name -> 值 “张三”
      • 字段 age -> 值 “28”
      • 字段 city -> 值 “北京” 这样数据在逻辑上更紧凑,管理起来也更方便,你可以一次性获取、修改整个对象,也可以单独操作某个字段。
  2. 字段和值:哈希里的“字段”就像是表格的列名(如name, age),“值”就是对应单元格里的数据,字段在同一个哈希内是唯一的,但不同的哈希可以有相同的字段名,值通常是字符串,但Redis现在也支持一些更复杂的情况(比如嵌套结构,但那个比较高级,先不管)。

  3. 操作灵活:你可以对哈希进行非常精细的操作。

    • 单独设置/获取一个字段的值:HSET user:1001 name 张三HGET user:1001 name
    • 一次性设置/获取所有字段和值:HMSET(旧命令)或 HSET(新用法), HGETALL
    • 只获取所有字段名:HKEYS
    • 让某个数字字段自增:HINCRBY user:1001 age 1 (年龄加1)。

当你需要保存一个具有多种属性的对象时,比如用户信息、商品信息、配置项等,哈希是你的首选,它让数据更有组织,避免了键名的泛滥。

总结一下根本区别

  • 集合 关心的是 “谁在这个俱乐部里”,成员本身是简单的、独立的个体(比如用户名、标签名),重点是成员的唯一性和成员之间的关系(交集并集等)。
  • 哈希 关心的是 “这个事物的详细信息是什么”,它把一个键(代表一个事物)的详细信息,拆解成多个方面(字段)来描述,重点是结构化地存储一个复杂对象的属性。

希望这样理一理之后,你能更清晰地知道在什么场景下该用集合,什么场景下该用哈希了,简单说,要存一堆不重复的、可能要算关系的“东西”,用集合;要存一个“东西”的详细“档案”,用哈希。

Redis里集合和哈希那些概念,感觉得重新理一理才能明白到底啥意思