暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Redis 数据结构之集合(Set)

Dtalk 2021-06-21
2104

作者简介

作者:冀浩东,转转数据库存储负责人,架构师


Redis 集合(Set)类型和数学中的集合类似,数学集合的概念是指具有某种特定性质的具体的或抽象的对象汇总而成的集体。简而言之,Redis集合就是一些不重复值的组合。利用集合(Set)这个数据结构,Redis 可以存储一些集合类型的数据,Redis也通过一些简便的命令很好的支持了交集、并集和差集等集合的基本运算。


常见的应用场景有:投票系统、标签系统、共同好友、共同关注、共同爱好、抽奖、商品筛选栏,访问IP统计等。


本文主要分为以下三部分:

1.  集合(Set)数据结构

2. 常用命令

3. 总结


01

Set 数据结构

Redis 中的集合(Set)内部编码是 intset 和 hashtable 两种实现方式,其中 intset 编码会使用更少的内存,查询效率较快,但是仅能存储整型数据,而 hashtable 则可以存储更多类型的数据,应用场景更加通用。


当集合对象满足以下两个条件时, 对象使用 intset 编码:

  • 集合所有成员类型都是整型;

  • 集合大小 (成员数量)不能超过 set-max-intset-entries, 默认 512。

以下是 intset 结构展示的一个集合对象:

intset 节点结构定义:

    typedef struct intset {
       uint32_t encoding;
       uint32_t length;
       int8_t contents[];
    } intset;

    结构定义说明:

    • encoding  编码方式

    • length  集合中包含的元素数量

    • contents 保存元素的数组


    当 intset 编码条件不能满足时,集合对象的编码会执行转换操作,原本的 intset 的所有元素会被保存到 hashtable 编码中。

    为了减少编码转换操作,建议提前规划好应用场景。

    以下是 hashtable 结构展示的一个集合对象:


    具体  hashtable 数据结构可以参考文章:

    Redis 数据结构之哈希(Hash)


    Redis 集合(Set)编码设计:对于少量整型数据可以使用 intset,对于其他类型的数据可以使用 hashtable,可以有效的减少内存开销,并且加快查询效率。同时丰富的操作命令降低了用户构建业务系统的学习开发成本,通过这样的灵活的数据结构,构建更加多样的业务场景。



    02

    常用命令

    1. 向集合添加一个或多个成员

    命令

    SADD key member [member ...]

      redis> SADD idbset i d b
      (integer) 3

      2. 获取集合的成员数

      命令

      SCARD key 

        redis> SCARD idbset
        (integer) 3

        3. 返回集合中的所有成员

        命令

        SMEMBERS key

          redis> SMEMBERS idbset
          1) "b"
          2) "i"
          3) "d"

          4. 判断 member 元素是否是集合 key 的成员

          命令

          SISMEMBER key member

            redis> SISMEMBER idbset "i"
            (integer) 1  # 存在成员 i
            redis> SISMEMBER idbset "x"
            (integer) 0  # 不存在成员 x

            5. 移除并返回集合中的一个或多个随机元素

            命令

            SPOP key [count]

              redis> SADD idbset i d b 1 2 3 4
              (integer) 7
              redis> spop idbset 3
              1) "3"
              2) "b"
              3) "4"

              6. 移除集合中一个或多个成员

              命令

              SREM key member [member ...]

                redis> SADD idbset i d b 1 2 3 4
                (integer) 7
                redis> SREM idbset 1 2 3 4
                (integer) 4
                redis> SMEMBERS idbset
                1) "b"
                2) "d"
                3) "i"

                7. 将 member 元素从 source 集合移动到 destination 集合

                命令

                SMOVE source destination member

                  redis> sadd oldset 1 2 3
                  (integer) 3
                  redis> SMOVE oldset newset 1
                  (integer) 1
                  redis> SMOVE oldset newset 2
                  (integer) 1
                  redis> SMEMBERS newset
                  1) "1"
                  2) "2"
                  redis> SMEMBERS oldset
                  1) "3"

                  8. 返回集合中一个或多个随机成员(不移除成员)

                  命令

                  SRANDMEMBER key [count]

                    redis> SMEMBERS idbset
                    1) "b"
                    2) "d"
                    3) "i"
                    redis> SRANDMEMBER idbset
                    "b"
                    redis> SRANDMEMBER idbset
                    "i"
                    redis> SRANDMEMBER idbset
                    "d"
                    redis> SRANDMEMBER idbset
                    "d"

                    9. 返回或保存第一个集合与其他集合之间的差异

                    命令

                    SDIFF key [key ...]

                    SDIFFSTORE destination key [key ...]

                      redis> SADD aset 1 2 3 4
                      (integer) 4
                      redis> SADD bset 3 4 5 6
                      (integer) 4
                      # aset 和 bset 的差异
                      redis> SDIFF aset bset
                      1) "1"
                      2) "2"
                      # bset 和 aset 的差异
                      redis> SDIFF bset aset
                      1) "5"
                      2) "6"


                      # 返回 aset 和 bset 的差异并存储在 cset 中
                      redis> SDIFFSTORE cset aset bset
                      (integer) 2
                      redis> SMEMBERS cset
                      1) "1"
                      2) "2"

                      10. 返回或保存给定所有集合的交集

                      命令

                      SINTER key [key ...]

                      SINTERSTORE destination key [key ...]

                        redis> SADD aset 1 2 3 4
                        (integer) 4
                        redis> SADD bset 3 4 5 6
                        (integer) 4


                        # 返回 aset 与 bset 的交集
                        redis> SINTER aset bset
                        1) "3"
                        2) "4"


                        # 返回 aset 与 bset 的交集并保存到 dset
                        redis> SINTERSTORE dset aset bset
                        (integer) 2
                        redis> SMEMBERS dset
                        1) "3"
                        2) "4"

                        11. 返回或保存所有给定集合的并集

                        命令

                        SUNION key [key ...]

                        SUNIONSTORE destination key [key ...]

                          redis> SUNION aset bset
                          1) "1"
                          2) "2"
                          3) "3"
                          4) "4"
                          5) "5"
                          6) "6"
                          redis> SUNIONSTORE cset aset bset
                          (integer) 6
                          redis> SMEMBERS cset
                          1) "1"
                          2) "2"
                          3) "3"
                          4) "4"
                          5) "5"
                          6) "6"

                          12. 迭代集合中的元素

                          命令

                          SSCAN key cursor [MATCH pattern] [COUNT count]

                            redis> SADD idbset a b c d e f g h
                            (integer) 8
                            redis> SSCAN idbset 0 match h* count 1
                            1) "4"
                            2) (empty list or set)
                            redis> SSCAN idbset 4 match h* count 1
                            1) "1"
                            2) (empty list or set)
                            redis> SSCAN idbset 1 match h* count 1
                            1) "5"
                            2) 1) "h"
                            redis> SSCAN idbset 5 match h* count 1
                            1) "3"
                            2) (empty list or set)
                            redis> SSCAN idbset 3 match h* count 1
                            1) "7"
                            2) (empty list or set)
                            redis> SSCAN idbset 7 match h* count 1
                            1) "0"
                            2) (empty list or set)

                            03

                            总结


                            往期 · 推荐

                            Redis 数据结构之列表(List)

                            Redis 数据结构之哈希(Hash)

                            Redis 数据结构之字符串 (String)

                            Dtalk - 开发者说Redis系列

                            文章转载自Dtalk,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                            评论