关于redis:闲扯Redis九Redis五种数据类型之Set型

49次阅读

共计 3067 个字符,预计需要花费 8 分钟才能阅读完成。

一、前言

Redis 提供了 5 种数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(汇合)、Zset(有序汇合),了解每种数据类型的特点对于 redis 的开发和运维十分重要。

<p align=”right”> 原文解析 </p>

Redis 中的 Set 是咱们常常应用到的一种数据类型,依据应用形式的不同,能够利用到很多场景中。

二、底层实现

 汇合对象的编码能够是 intset 或者 hashtable。

 intset 编码的汇合对象应用整数汇合作为底层实现,汇合对象蕴含的所有元素都被保留在整数汇合外面。

 举个例子,以下代码将创立一个如图 8-12 所示的 intset 编码汇合对象:

redis> SADD numbers 1 3 5
(integer) 3

结构图 8-12:

 另一方面,hashtable 编码的汇合对象应用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象蕴含了一个汇合元素,而字典的值则全副被设置为 NULL。

举个例子,以下代码将创立一个如图 8-13 所示的 hashtable 编码汇合对象:

redis> SADD fruits "apple" "banana" "cherry"
(integer) 3

结构图 8-13:

三、编码转换

 当汇合对象能够同时满足以下两个条件时,对象应用 intset 编码:

1. 汇合对象保留的所有元素都是整数值;
2. 汇合对象保留的元素数量不超过 512 个;

 不能满足这两个条件的汇合对象须要应用 hashtable 编码。

留神 : 第二个条件的上限值是能够批改的,具体请看配置文件中对于 set-max-intset-entries 选项的阐明。对于应用 intset 编码的汇合对象来说,当应用 intset 编码所需的两个条件的任意一个不能被满足时,对象的编码转换操作就会被执行:本来保留在整数汇合中的所有元素都会被转移并保留到字典外面,并且对象的编码也会从 intset 变为 hashtable。

 举个例子,以下代码创立了一个只蕴含整数元素的汇合对象,该对象的编码为 intset:

redis> SADD numbers 1 3 5
(integer) 3

redis> OBJECT ENCODING numbers
"intset"

 不过,只有咱们向这个只蕴含整数元素的汇合对象增加一个字符串元素,汇合对象的编码转移操作就会被执行

redis> SADD numbers "seven"
(integer) 1

redis> OBJECT ENCODING numbers
"hashtable"

 除此之外,如果咱们创立一个蕴含 512 个整数元素的汇合对象,那么对象的编码应该会是 intset:

redis> EVAL "for i=1, 512 do redis.call('SADD', KEYS[1], i) end" 1 integers
(nil)

redis> SCARD integers
(integer) 512

redis> OBJECT ENCODING integers
"intset"

 然而,只有咱们再向汇合增加一个新的整数元素,使得这个汇合的元素数量变成 513,那么对象的编码转换操作就会被执行:

redis> SADD integers 10086
(integer) 1

redis> SCARD integers
(integer) 513

redis> OBJECT ENCODING integers
"hashtable"

四、命令实现

 因为汇合键的值为汇合对象,所以用于汇合键的所有命令都是针对汇合对象来构建的,以下表格列出了其中一部分汇合键命令,以及这些命令在不同编码的汇合对象下的实现办法。

命令 intset 编码的实现办法 hashtable 编码的实现办法
SADD 调用 intsetAdd 函数,将所有新元素增加到整数汇合外面。 调用 dictAdd,以新元素为键,NULL 为值,将键值对增加到字典外面。
SCARD 调用 intsetLen 函数,返回整数汇合所蕴含的元素数量,这个数量就是汇合对象所蕴含的元素数量。 调用 dictSize 函数,返回字典所蕴含的键值对数量,这个数量就是汇合对象所蕴含的元素数量。
SISMEMBER 调用 intsetFind 函数,在整数汇合中查找给定的元素,如果找到了阐明元素存在于汇合,没找到则阐明元素不存在于汇合。 调用 dictFind 函数,在字典的键中查找给定的元素,如果找到了阐明元素存在于汇合,没找到则阐明元素不存在于汇合。
SMEMBERS 遍历整个整数汇合,应用 intsetGet 函数返回汇合元素。 遍历整个字典,应用 dictGetKey 函数返回字典的键作为汇合元素。
SRANDMEMBER 调用 intsetRandom 函数,从整数汇合中随机返回一个元素。 调用 dictGetRandomKey 函数,从字典中随机返回一个字典键。
SPOP 调用 intsetRandom 函数,从整数汇合中随机取出一个元素,在将这个随机元素返回给客户端之后,调用 intsetRemove 函数,将随机元素从整数汇合中删除掉。 调用 dictGetRandomKey 函数,从字典中随机取出一个字典键,在将这个随机字典键的值返回给客户端之后,调用 dictDelete 函数,从字典中删除随机字典键所对应的键值对。
SREM 调用 intsetRemove 函数,从整数汇合中删除所有给定的元素。 调用 dictDelete 函数,从字典中删除所有键为给定元素的键值对。

五、利用场景

1. 抽奖

 抽奖
    1)用户参加抽奖:SADD order 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
    2)查看所有参加抽奖的人:SMEMBERS order
    3)反复抽奖每次抽取两人:SMEMBERS order 2
    4)不反复抽奖,三等奖 3 人,二等奖 2 人,一等奖 1 人
        SPOP order 3
        SPOP order 2
        SPOP order 1

2. 点赞、珍藏、标签

 点赞、珍藏、标签
    1)点赞的人:SADD like:1 1001 1002 1003 1004 1005
    2)勾销点赞:SREM like:1 1002
    3)检查用户是否点赞过:SISMEMBER like:1 1002
        SISMEMBER like:1 1005
    4)获取点赞人员列表:SMEMBERS like:1
    5)获取点赞总人数:SCARD like:1

3. 关注模型

redis> SADD wangwu zhangsan lisi zhaoliu haoba
    (integer) 4
redis> SADD zhangsan lisi wangwu sijiu
    (integer) 3
redis> SADD lisi zhaoliu zhangsan qinshi
    (integer) 3
redis> SINTER wangwu zhangsan
    1) "lisi"
redis> SISMEMBER zhangsan lisi
    (integer) 1
redis> SISMEMBER lisi zhangsan
    (integer) 1
redis> SISMEMBER zhaoliu zhangsan
    (integer) 0
redis> SISMEMBER haoba zhangsan
    (integer) 0
redis> SDIFF zhangsan wangwu
    1) "sijiu"
    2) "wangwu"
redis> SDIFF lisi wangwu
    1) "qinshi"

六、要点总结

(1)汇合对象的编码能够是 intset 或者 hashtable。

(2)intset 编码的汇合对象应用整数汇合作为底层实现。

(3)hashtable 编码的汇合对象应用字典作为底层实现。

(4)intset 与 hashtable 编码之间,符合条件的状况下,能够转换。

over

正文完
 0