关灯
护眼 字体:大
中
小
上一章
目录
下一章
集合(Sets)是Redis的基本数据结构之一。
Redis中的集合与列表一样可以存放很多数据,但不同之处在于:集合里面的数据不能重复,也没有顺序。由于没有顺序,所以自然没有方向,不存在“左右侧”之说。
Redis的集合与Python的集合有非常多的相似之处,可以对比学习。集合有15条操作命令,本节将介绍其中常用的9条命令。
5.4.1 使用redis-cli实现
1.插入数据
集合的首字母为“S”,“添加”的英文为“Add”,所以向集合中添加数据的命令为“sadd”,命令格式如下:
sadd key value1 value2 value3
key 的命名方式与字符串和列表一样,可以使用数字、字母、下划线和中文,但不建议使用中文。
Value可以有一个或者多个。如果有多个Value,则每一个之间使用空格隔开;如果一个Value内部本身就有空格,则使用引号把它包起来。
以下为使用示例:
命令执行效果如图5-44所示。
图5-44 向Redis的集合中添加数据
向Redis集合中添加数据的过程如图5-45所示。
图5-45 集合插入数据示意图
从图5-45可以看出,由于集合里面的数据是没有顺序的,所以:
● 数据插入命令执行的先后顺序无关紧要。
● 在一条命令中,数据位于“value1”还是“value3”也无关紧要。
由于集合的数据是不重复的,如果在一条命令中同一个数据既是“value1”又是“value2”会怎么样?如果多条命令都插入了同一个数据又会怎么样?下面通过实际执行命令来看效果。
sadd example_set python golang python C Java
sadd example_set python
运行效果如图5-46所示。
图5-46 往集合中插入重复数据
从图5-46可以看出,第一次尝试插入“python”“golang”“python”“C”“Java”一共5个值,但实际上,Redis返回的数字“4”表示实际上只插入了4个值。这是因为有两个“python”,集合自动过滤了第2个“python”。
接下来单独插入一个值“python”,Redis 返回0,表示实际上什么数据都没有添加进“example_set”这个集合中。因为原来已经有“python”这个值了,所以,集合不再接收重复的数据。
2.读取数据
集合里面的数据虽然没有顺序也不能重复,但是可以查看集合里面一共有多少个数据。
(1)查询集合里面元素的数量。
查询集合数据量的命令是scard。其中,首字母“s”是“集合(Sets)”的首字母,“card”不是英文单词“卡片(Card)”,而是“基数(Cardinality)”的缩写。
命令格式如下:
scard key
例如执行以下命令:
scard example_set
执行效果如图5-47所示,表示集合“example_set”中有11条数据。
图5-47 查看集合内部有多少数据
(2)从集合中获取数据。
从集合中获取数据使用的命令为“spop”。由于集合里面的数据没有顺序,所以spop命令会随机获取集合中的数据,无法预测会获取哪一条数据。
“spop”命令的格式如下:
spop key count
其中,如果“count”省略,则表示随机获取1条数据。
● 如果“count”为其他大于1的整数,则会获取多条数据;
● 如果“count”对应的整数超过了集合总数据的条数,则获取集合中的所有数据,例如:
spop example_set
spop example_set 3
spop example_set 1000
运行效果如图5-48所示。获取一条数据后,这一条数据就被会被从集合中删除。
图5-48 从集合中弹出数据
(3)获取集合中的所有数据。
如果要获取所有数据,则可以使用以下命令:
smembers key
运行效果如图5-49所示。
图5-49 获取集合的所有数据
提示:
smembers命令不会删除数据。但是如果集合里的数据量极大,就应该慎重使用“获取所有数据”,因为这样会导致系统的I/O资源瞬间被耗尽。
(4)判断集合中是否包含某个元素。
sadd命令在遇到数据已经存在时,会返回“0”,如果数据不存则把数据插入再返回“1”。所以,这一条命令可以通过返回的数字来判断数据是否存在。
如果不想把数据插入集合,只是单纯想检查数据是否在集合中,那就要使用“sismember”命令。“sismember”命令的使用格式如下:
sismember key value
如果数据存在,则返回“1”;如果数据不存在,则返回“0”。例如:
sismember example_set 2
sismember example_set xxxx
运行效果如图5-50所示,如果看到“2”则表示数据是已经存在的,而如果看到“xxxx”则表示数据是不存在的。
图5-50 检查数据是否在集合中
3.删除数据
如果要从集合中删除特定的数据,可以使用命令“srem”,格式为:
srem key value1 value2 value3
例如:
srem example_set 2
运行效果如图5-51所示。
图5-51 从集合中删除数据
提示:
从效果上看,检查数据是否在集合中且不把数据添加进集合中有两种写法:
(1)直接使用“sismember”命令。
(2)使用“sadd”命令,如果返回“1”,则再使用“srem”命令把添加的这一条数据移除。
它们的区别在于:
● 方式(1)不论集合中有多少数据,检查的时间都相同。
● 方式(2)的时间会随着集合中数据量的增加而增加。
● 方式(2)有两步,假设刚刚执行了第一条命令,还没有来得及删除数据,此时另一台服务器又去检查这个数据是否存在,就会导致结果出错。
4.集合的交集
在数学中,“集合”包括“交集”“并集”“差集”的概念。在 Redis 的集合中也存在这样的概念。
有两个集合A和B。交集是指,既属于A,又属于B的数据构成的集合。
假设:A集合中的内容为{1, 'C', 'three', 'python', 2,’三’}, B集合中的内容为{9,8.0,'VI',’七’,'python',2}。
则:A与B的交集就是{2, 'python'},如图5-52中的阴影部分所示。
图5-52 阴影部分为交集
在Redis中,求集合交集使用的命令为“sinter”,命令格式如下:
sinter key1 key2 key3
如果有多个key,那么就是求所有key对应的集合的交集。实例代码如下:
运行效果如图5-53所示。
图5-53 求集合的交集
5.集合的并集
集合的“并集”是指,只属于集合A的数据与只属于集合B的数据,以及既属于A又属于B的数据构成的集合,集合A与集合B都有的数据需要去重。
假设:A集合中的内容为{1, 'C', 'three', 'python', 2,’三’}, B集合中的内容为{9,8.0,'VI',’七’,'python',2}。
则:A与B的并集就是{1, 'C', 'three', 'python', 2,’三’, 9, 8.0, 'VI', ’七’},如图5-54中的阴影部分所示。
图5-54 阴影部分为并集
求集合并集使用的命令为“sunion”,命令格式如下:
sunion key1 key2 key3
如果有超过两个key,那么就是求所有集合的并集。实例代码如下:
运行效果如图5-55所示。
图5-55 求集合的并集
6.集合的差集
集合的“差集”是指,只属于一个集合,不属于其他集合的数据构成的集合。
假设:A集合中的内容为{1, 'C', 'three', 'python', 2,’三’}, B集合中的内容为{9,8.0,'VI',’七’,'python',2}。
则:A与B的差集就是{1, 'C', 'three', ’三’},如图5-56中的阴影部分所示。
图5-56 阴影部分为集合A对集合B的差集
求集合差集使用的命令是“sdiff”,命令格式如下:
sdiff key1 key2 key3
意思是,求所有只在key1对应的集合中有,在key2、key3……集合中没有的数据构成的集合。实例代码如下:
运行效果如图5-57所示。
图5-57 求集合的差集
5.4.2 使用Python实现
使用Python操作Redis集合相关的关键字与redis-cli的命令完全相同,唯一的差别在于参数的传入方式。
1.插入数据
使用Python向Redis集合中添加数据,用到的关键字是“sadd”。实例代码如下:
代码5-12 在Python中向Redis集合插入数据
代码返回的数字表示当前添加了几条数据。运行效果如图5-58所示。
图5-58 使用Python添加数据到集合中
如果数据已经在集合中,则Python是不会把它重复添加进去的,见下方代码:
>>> client.sadd('example_set_python', 'some_data')
1
>>> client.sadd('example_set_python', 'some_data')
0
运行效果如图5-59所示。在数据不存在时添加,则返回1;在数据已经存在时添加,则返回0。
图5-59 添加重复数据返回0
2.读取数据
使用关键字“scard”可以查看集合中数据的条数,使用关键字“spop”可以从集合中随机获取一条数据。
代码5-13 在Python中读取Redis集合的数据
运行效果如图5-60所示。获取的数据均为bytes型数据。
图5-60 获取集合数据条数与弹出数据
提示:
在Python中,“spop”关键字没有“count”参数,因此一次只能获取一条数据,不能一次性获取多条数据。如果要一次获取多条数据,则可以使用循环来实现,见代码5-13。
代码5-13 使用循环从Redis集合中获取数据
运行效果如图5-61所示。
图5-61 使用循环来间接获取多条数据
获取集合所有数据的关键字为“smembers”。以下是一个示例:
代码5-14 获取Redis集合中的全部数据
运行效果如图5-62所示。
图5-62 获取集合中的全部数据
从图5-62可以看出,关键字“smembers”返回的数据格式是Python中的“集合(set)”,且里面的每一个数据都是bytes型数据。
3.删除数据
从集合中移除数据使用的关键字为“srem”。以下是一个示例:
代码5-15 从Redis集合中删除数据
运行效果如图5-63所示。
图5-63 从集合中移除数据
4.集合的运算
交集、并集和差集用到的关键字和redis-cli中的命令是一样的,分别是“sinter”“sunion”和“sdiff”。以下是一个实例。
代码5-16 使用Python计算Redis的集合的交集并集和差集
运行效果如图5-64所示。
图5-64 在Python中求交集、并集和差集
提示:
求差集时,参数的顺序是很重要的,最后的结果是用第1个Key对应的集合中的数据扣除后面的Key对应的集合中的数据。
5.4.3 集合的应用
在工程中,Redis的集合一般有两种用途:
(1)根据集合内数据不重复的特性实现去重并记录信息。
(2)利用多个集合计算交集、并集和差集。
假设,要做一个学生选课情况实时监控系统,则需要实时知道以下几个数据:
(1)当前一共有多少学生至少选了一门课。
(2)选了A课没有选B课的学生有多少。
(3)既选了A课又选了B课的学生有多少。
(4)A、B两门课至少选了一门的学生有多少。
使用集合可以轻易实现这样的功能。每一门课作为一个集合,里面的值就是每一个学生的学号,如图5-65所示。
图5-65 模拟课程集合
通过求交集并集和差集就能实现上面的要求了。
主要代码如下:
代码5-17 使用Redis集合运算计算学生选课信息
其中,第31行代码表示:只有在这个程序被直接运行时才运行下面的四行代码;如果是被其他代码作为模块带入,则不运行后面的四行代码。
本章小结
本章主要介绍了 Redis 的安装和三种基本数据结构——字符串、列表和集合的使用。在学习这三种数据结构时,建议读者使用Python来操作,同时设想一些使用场景来帮助自己更好地理解。
上一章
目录
下一章