《闲扯Redis九》Redis五种数据类型之Set型
一、前言
Redis 提供了5种数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)、Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要。

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
《闲扯Redis九》Redis五种数据类型之Set型的更多相关文章
- 《闲扯Redis一》五种数据类型之String型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
- Redis支持的五种数据类型
redis支持的五种数据类型: 1.string(字符串) 2.hash(哈希) Redis hash 是一个键值(key=>value)对集合. Redis hash是一个string类型的f ...
- 【Redis】一、Redis简介及五种数据类型
(一)Redis简介 Redis(Remote Dictionary Server)是一个使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value的开源 ...
- 《闲扯Redis三》Redis五种数据类型之List型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
- 《闲扯Redis六》Redis五种数据类型之Hash型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
- Redis安装及五种数据类型
redis是非关系型数据库,也叫内存数据库.数据是键值对的形式,通过key查找value 安装Radis:6379 sudo apt-get update sudo apt-get install r ...
- Redis学习笔记--五种数据类型的使用场景
String 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...
- <Redis> 入门二 五种数据类型的操作、通用key的操作、发布订阅
文档参考:http://www.redis.net.cn/ string - > key value 简单的keyvalue,常规计数:例如微博数,粉丝数 set -> key v ...
- redis五种数据类型的使用(zz)
redis五种数据类型的使用 redis五种数据类型的使用 (摘自:http://tech.it168.com/a2011/0818/1234/000001234478_all.shtml ) 1.S ...
随机推荐
- Spring设置启动时执行方法
@PostConstruct方法 在实现类和方法上加注解,类上加bean注解,方法上加@PostConstruct注解. @PostConstruct//启动执行public void refresh ...
- 循环中的自变量-break和continue
1.break 作用:break 用于终止循环的执行, 过程:当执行到break语句后,程序将跳出循环,执行循环语句后边的代码 i=1 while i<10: if i==5: break pr ...
- 编辑器之神_vim
01vim简介 1.什么是vim: 文本编辑器 2.vim特点: 没有图形界面;只能是编辑文本内容;没有菜单 ;只有命令 3.在很多linux发行版中,直接把vi作为vim的软连接 02打开和新建文件 ...
- (私人收藏)Linux命令大全(修正版)
Linux命令大全(修正版) https://pan.baidu.com/s/1tPTv1PzCelBC_Eq-ASAOBg1yp3 文件传输 bye ftp ftpcount ftpshut ftp ...
- java语言基础(三)_数组
数组 是引用类型 1. 容器:是将多个数据存储到一起,每个数据称为该容器的元素. 2. 数组概念:数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致. 特点: 数组是一种引用数据类型 数组当 ...
- HDU 4143 A Simple Problem 题解
题目 For a given positive integer n, please find the saallest positive integer x that we can find an i ...
- 51nod1524 最大子段和V2
题干 N个整数组成的序列a[1],a[2],a[3],-,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数 ...
- H3c实验室-(OSPF,Nat,STP,Dhcp,Acl)v.1)
实验声明 本实验纯属学习记录性质,如有错误,请大哥帮忙提出,马上改正谢谢~还有学习H3c心态要好,他有超级多的bug!!!! 实验介绍 实验条件 实验开始 把图设计好 先说明一下RTA-RTB的线路是 ...
- Node js 入门指南(1)
目录 Node Js 定义 特点 Node使用方式 Tip: 使用导出文件的注意事项 Node 内置模块 http 模块 定义 使用方法 fs 模块 定义 使用方法 读取文件方式 同步读取 异步读取 ...
- 开源利器分享:BitBar 坐看今天你的项目涨了多少 star
今天开头我想叨叨几句,我个人最近的感受.在这个信息爆炸,互联网的时代里.我的周遭总是充斥者着各种让人能产生焦虑的信息, 我不知道有没有小伙伴和我一样,看到各种神通广大.游戏人生的大侠,低头看看自己当前 ...