这是我参与更文挑战的第14天,活动详情查看:更文挑战
Redis集合对象的成员是唯一的,这就意味着集合中不能出现重复的数据。Redis 中集合对象的编码可以是intset或者hashtable,所以添加,删除,查找的复杂度都是O(1)。集合中最大的成员数为 (4294967295, 每个集合可存储40多亿个成员)。
Redis 集合对象的常用命令
SADD key member1 [member2] //向集合添加一个或多个成员
SCARD key //获取集合的成员数
SDIFF key1 [key2] //返回给定所有集合的差集
SDIFFSTORE destination key1 [key2] //返回给定所有集合的差集并存储在 destination 中
SINTER key1 [key2] //返回给定所有集合的交集
SINTERSTORE destination key1 [key2] //返回给定所有集合的交集并存储在 destination 中
SISMEMBER key member //判断 member 元素是否是集合 key 的成员
SMEMBERS key //返回集合中的所有成员
SMOVE source destination member //将 member 元素从 source 集合移动到 destination 集合
SPOP key //移除并返回集合中的一个随机元素
SRANDMEMBER key [count] //返回集合中一个或多个随机数
SREM key member1 [member2] //移除集合中一个或多个成员
SUNION key1 [key2] //返回所有给定集合的并集
SUNIONSTORE destination key1 [key2] //所有给定集合的并集存储在 destination 集合中
SSCAN key cursor [MATCH pattern] [COUNT count] //迭代集合中的元素
1.集合对象编码
intset 编码的集合对象使用整数集合作为底层实现, 集合对象包含的所有元素都被保存在整数集合里面。如SADD numbers 1 3 5,创建一个含有1,3,5三个数的集合,底层结构如下:
hashtable 编码的集合对象使用字典作为底层实现, 字典的每个键都是一个字符串对象, 每个字符串对象包含了一个集合元素, 而字典的值则全部被设置为 NULL 。如SADD fruits "apple" "banana" "cherry"将创建如下集合对象:
2.编码的转换
当集合对象可以同时满足以下两个条件时, 对象使用 intset 编码:
-
集合对象保存的所有元素都是整数值;
-
集合对象保存的元素数量不超过
512个(上限值是可以修改的, 具体请看配置文件中关于set-max-intset-entries选项说明);
不能满足这两个条件的集合对象需要使用 hashtable 编码。
3.整数集合的实现
整数集合结构如下:
typedef struct intset {
// 编码方式
uint32_t encoding;
// 集合包含的元素数量
uint32_t length;
// 保存元素的数组
int8_t contents[];
} intset;
-
contents数组是整数集合的底层实现: 整数集合的每个元素都是contents数组的一个数组项(item), 各个项在数组中按值的大小从小到大有序地排列, 并且数组中不包含任何重复项。 -
length属性记录了整数集合包含的元素数量, 也即是contents数组的长度。 -
虽然
intset结构将contents属性声明为int8_t类型的数组, 但实际上contents数组并不保存任何int8_t类型的值 ——contents数组的真正类型取决于encoding属性的值:- 如果
encoding属性的值为INTSET_ENC_INT16, 那么contents就是一个int16_t类型的数组, 数组里的每个项都是一个int16_t类型的整数值 (最小值为-32,768,最大值为32,767)。 - 如果
encoding属性的值为INTSET_ENC_INT32, 那么contents就是一个int32_t类型的数组, 数组里的每个项都是一个int32_t类型的整数值 (最小值为-2,147,483,648,最大值为2,147,483,647)。 - 如果
encoding属性的值为INTSET_ENC_INT64, 那么contents就是一个int64_t类型的数组, 数组里的每个项都是一个int64_t类型的整数值 (最小值为-9,223,372,036,854,775,808,最大值为9,223,372,036,854,775,807)。
- 如果
注:有关hashtable的实现,可以看Redis基础系列(四)——哈希对象