Redisbook学习笔记(3)数据类型之集合

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介:

REDIS_SET 集合 是SADD 、SRANDMEMBER 等命令的操作对象 它使用

REDIS_ENCODING_INTSET 和REDIS_ENCODING_HT 两种方式编码

wKioL1MMhAygab3HAACc0PuXNzw010.jpg

编码的选择

第一个添加到集合的元素决定了创建集合时所使用的编码

如果第一个元素可以表示为long long 类型值也即是它是一个整数那么集合的初

始编码为REDIS_ENCODING_INTSET 。

否则集合的初始编码为REDIS_ENCODING_HT 。

编码的切换

如果一个集合使用REDIS_ENCODING_INTSET 编码那么当以下任何一个条件被满足时这个

集合会被转换成REDIS_ENCODING_HT 编码

intset 保存的整数值个数超过server.set_max_intset_entries 默认值为512 。

试图往集合里添加一个新元素并且这个元素不能被表示为long long 类型也即是

它不是一个整数。

字典编码的集合

当使用REDIS_ENCODING_HT 编码时集合将元素保存到字典的键里面而字典的值则统一设

为NULL 。

作为例子以下图片展示了一个以REDIS_ENCODING_HT 编码表示的集合集合的成员为elem1

、elem2 和elem3

wKiom1MMhI-xzeHdAAEfGjLBdwo023.jpg

集合命令的实现

Redis 集合类型命令的实现主要是对intset 和dict 两个数据结构的操作函数的包装以及

一些在两种编码之间进行转换的函数大部分都没有什么需要解释的地方唯一比较有趣的是

SINTER 、SUNION 等命令之下的算法实现以下三个小节就分别讨论它们所使用的算法。

求交集算法

SINTER 和SINTERSTORE 两个命令所使用的求并交集算法可以用Python 表示如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# coding: utf-8
def sinter(*multi_set):
# 根据集合的基数进行排序
sorted_multi_set = sorted(multi_set, lambda x, y: len(x) - len(y))
# 使用基数最小的集合作为基础结果集有助于降低常数项
result = sorted_multi_set[0].copy()
# 剔除所有在sorted_multi_set[0] 中存在
# 但在其他某个集合中不存在的元素
for  elem in sorted_multi_set[0]:
for  s in sorted_multi_set[1:]:
if  (not elem in s):
result. remove (elem)
break
return  result

算法的复杂度为O(N2) 执行步数为S T 其中S 为输入集合中基数最小的集合而T 则

为输入集合的数量。

求并集算法

SUNION 和SUNIONSTORE 两个命令所使用的求并集算法可以用Python 表示如下

1
2
3
4
5
6
7
8
# coding: utf-8
def sunion(*multi_set):
result = set()
for  s in multi_set:
for  elem in s:
# 重复的元素会被自动忽略
result.add(elem)
return  result

算法的复杂度为O(N) 。

求差集算法

Redis 为SDIFF 和SDIFFSTORE 两个命令准备了两种求集合差的算法。

以Python 代码表示的算法一定义如下

1
2
3
4
5
6
7
8
9
10
11
12
# coding: utf-8
def sdiff_1(*multi_set):
result = multi_set[0].copy()
sorted_multi_set = sorted(multi_set[1:], lambda x, y: len(x) - len(y))
# 当elem 存在于除multi_set[0] 之外的集合时
# 将elem 从result 中删除
for  elem in multi_set[0]:
for  s in sorted_multi_set:
if  elem in s:
result. remove (elem)
break
return  result

这个算法的复杂度为O(N2) 执行步数为S T 其中S 为输入集合中基数最小的集合而

T 则为除第一个集合之外其他集合的数量。


以Python 代码表示的算法二定于如下

1
2
3
4
5
6
7
8
9
10
# coding: utf-8
def sdiff_2(*multi_set):
# 用第一个集合作为结果集的起始值
result = multi_set[0].copy()
for  s in multi_set[1:]:
for  elem in s:
# 从结果集中删去其他集合中包含的元素
if  elem in result:
result. remove (elem)
return  result

这个算法的复杂度同样为O(N2) 执行步数为S 其中S 为所有集合的基数总和。

Redis 使用一个程序决定该使用那个求差集算法程序用Python 表示如下

1
2
3
4
5
6
7
8
9
10
11
12
# coding: utf-8
from sdiff_1 import sdiff_1
from sdiff_2 import sdiff_2
def sdiff(*multi_set):
# 算法一的常数项较低给它一点额外的优先级
algo_one_advantage = 2
algo_one_weight = len(multi_set[0]) * len(multi_set[1:]) / algo_one_advantage
algo_two_weight = sum(map(len, multi_set))
if  algo_one_weight <= algo_two_weight:
return  sdiff_1(*multi_set)
else :
return  sdiff_2(*multi_set)
























本文转自shayang8851CTO博客,原文链接:http://blog.51cto.com/janephp/1363456 ,如需转载请自行联系原作者
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3天前
|
机器学习/深度学习 存储 数据挖掘
Python从入门到精通——学习基础语法和数据类型 1.2.1变量、整数、浮点数、字符串、布尔值、列表、元组、字典和集合。
Python从入门到精通——学习基础语法和数据类型 1.2.1变量、整数、浮点数、字符串、布尔值、列表、元组、字典和集合。
|
8月前
|
存储 数据挖掘 Linux
Python学习笔记丨数据类型基础与易错点总结,列表、字典、集合、数值、字符串、元组
Python学习笔记丨数据类型基础与易错点总结,列表、字典、集合、数值、字符串、元组
|
索引
学习TypeScrip9(元组类型)
元组与集合的不同之处在于,元组中的元素类型可以是不同的,而且数量固定。元组的好处在于可以把多个元素作为一个单元传递。如果一个方法需要返回多个值,可以把这多个值作为元组返回,而不需要创建额外的类来表示。
60 0
学习TypeScrip9(元组类型)
|
开发者 Python
数组类型|学习笔记
快速学习数组类型
69 0
|
开发者 Python
可变数据类型和不可变数据类型 | 学习笔记
快速学习可变数据类型和不可变数据类型,介绍了可变数据类型和不可变数据类型系统机制, 以及在实际应用过程中如何使用。
100 0
可变数据类型和不可变数据类型 | 学习笔记
|
存储 Go 开发者
整数类型使用细节|学习笔记
快速学习整数类型使用细节。
63 0
|
缓存 安全 Java
【探究为什么String类是不可变类型:String类仿写】
【探究为什么String类是不可变类型:String类仿写】
81 0