Redis-Set篇

基础命令

  • sadd key [values] :向集合添加一个或多个成员
  • scard key:获取集合的成员数
  • spop key: 随机弹出一个元素(随机)
  • sismember key member:判断 member 元素是否是集合 key 的成员
  • srem key [members]:移除集合中一个或多个元素(指定)
myRedis:0>sadd key1 test1 test2
"2"

myRedis:0>sadd key1 test3 test4
"2"

myRedis:0>scard key1
"4"

myRedis:0>sismember key1 test4
"1"

myRedis:0>sismember key1 test5
"0"

myRedis:0>spop key1
"test4"

myRedis:0>spop key1
"test2"

myRedis:0>srem key1 test1
"1"

myRedis:0>scard key1
"1"
  • sdiff key1 [keys] : 返回第一个集合与后面集合的差集
  • sinter key1 [keys]:返回给定所有集合的交集
  • sunion key1 [keys] :返回所有给定集合的并集
myRedis:0>sadd key1 test1 test2 test3 test4 test5
"5"

myRedis:0>sadd key2 test2 test4 test6 test7 test8
"5"

myRedis:0>sadd key3 test2 test4 test8 test9 test10 
"5"

myRedis:0>sdiff key1 key2 key3
 1)  "test3"
 2)  "test5"
 3)  "test1"

myRedis:0>sinter key1 key2 key2
 1)  "test2"
 2)  "test4"

myRedis:0>sunion  key1 key2 key3
 1)  "test6"
 2)  "test9"
 3)  "test1"
 4)  "test3"
 5)  "test5"
 6)  "test4"
 7)  "test7"
 8)  "test8"
 9)  "test2"
 10)  "test10"

存储编码

Redis的集合内部编码有两种

  • intset
  • hashtable(在上一篇章中已经详细介绍Redis-Hash篇
intset源码分析

源码位置:intset.h

typedef struct intset {
    uint32_t encoding; // intset的内部编码,int16_t,int32_t,int64_t
    uint32_t length;  // 集合的元素数量
    int8_t contents[]; // 保存元素的数组
} intset;
intset存储图解分析

在这里插入图片描述

intset内部编码升级
  • intset内部编码简介
    虽然contents类型是int8,但是实际上的编码则是由encoding决定的,而encoding在集合的内部编码中有三种值:
    • INTSET_ENC_INT16 范围:-32768 ~ 32767(-2^15 ~ 2^15-1)
    • INTSET_ENC_INT32 范围: -2147483648 ~ 2147483647(-2^31 ~ 2^31-1)
    • INTSET_ENC_INT64 范围:-9223372036854775808 ~ 9223372036854775807(-263^ ~ 2^63-1)
  • 为什么要升级
    • 将一个新元素添加到集合里面,并且新元素的类型比现有元素的类型都要长时,集合就要新进行升级才能存的下新元素
  • 升级的步骤
    • 根据新元素的类型,扩展底层数据的空间大小
    • 将现有的元素都转换成新元素相同的类型,并将转换后的原始元素放到正确的位置上(顺序不变:拷贝过程)
    • 添加新元素到底层数组里
  • 升级的好处
    • 提升整数集合的灵活性
    • 尽可能的节约内存
  • 降级
    • 升级后不支持降级操作,即使把所有超长的元素删了之后,内部编码也不会降低,升级过程不可逆
图解升级步骤
  • 假设原始值存的是1 2 3
1 2 3 选用int16类型即可存储,初始值都是16位=>2字节

补充扩展:1字节=8位
在这里插入图片描述

  • 在初始值的基础上插入一个新元素 100000
新元素100000 已经超出了int16的范围,如果想插入需要使用int32类型
因此接下来要做的事情就是,升级数据类型到int32

注意:这里会按照新的类型和元素个数申请新的空间
总空间大小为:32*4=128位(16字节)
需要申请的大小为:128-48 = 80位

在这里插入图片描述

  • 新的空间申请好之后,会修改原始数据的类型重新调整内存分配
按照四个元素计算,每个元素占用32位,从大到小依次调整元素的位置

在这里插入图片描述
依次类推,调整2 1的位置,最后会得到如下结构
在这里插入图片描述

  • 调整好原始数据的内存分配之后,再把新的元素插入到指定位置
    在这里插入图片描述
  • 修改encoding为int32_t,修改length为4,新增元素结束
set编码转换条件
  • 集合对象保存的所有元素都是整数值
  • 集合元素数量小于等于512个
    以上条件同时满足,set集合内部编码使用的是intset,否则会用hashtable存储
  • hashtable再之前的篇章中已经说过了,区别点在于,hashtable存储集合时用的是key,value为空

结尾语

Redis中的集合重要特征是不重复,非整数类型无序,存整数和存其他类型的用两种不同的编码实现,而如何创建一个有序的集合,将在下一篇章中介绍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值