本文会对redis中的集合对象进行学习。关于对象是什么,之前已经总结过,本文不再赘述,直接开始介绍集合对象。
集合的对象编码可以使intest或者hashtable。具体使用什么编码,也是取决于存储的键值对。
当同时满足以下两个条件时,使用intest编码:
不满足以上两个条件的,均使用hashtable编码。
当一个集合只包含整数值元素,并且元素不多时,redis就会用intset作为集合的底层实现。
先看一下intset.h中对intset struct的定义:
typedef struct intset {
//编码方式
uint32_t encoding;
//集合包含的元素数量
uint32_t length;
//保存元素的数组
int8_t contents[];
} intset;
从定义能很清楚的看到数组contents是整数集合的底层实现。在contents中,整数值按从小到大的顺序进行排列,并且无重复数据。length集合的数量,也就是contents的长度。
注:contents虽然是int8_t类型,但是并不保存任何int8_t类型的值,保存值的类型取决于encoding。
如果新加入contents的元素类型比当前contents中元素类型都要长时,那么intset就会进行升级操作。
例如现在contents中都是int16_t类型的数据,现在一个int32_t类型的数据要插入,那么就需要将之前contents中8位的元素扩展为16位。
例:现有3个int16位的元素,要插入一个int32的元素,那么前面3个也都要改成32位,因此空间变成4*32=128位
位 | 0~15 | 16~31 | 32~47 | 48~127 |
---|---|---|---|---|
元素 | 1 | 2 | 3 | new |
分配好空间后,要开始对之前的3个元素做类型转换:
位 | 0~31 | 32~63 | 64~95 | 96~127 |
---|---|---|---|---|
元素 | 1 | 2 | 3 | 4 |
之前的元素3移到64~95位,再依次移动元素2,元素1,最后插入新的元素。
类型改完之后,将encoding变为32位的,length从3改为4.
hash之前讲过,这里不讲了
跟之前讲hash一样,多用help命令,可以查看set下的所有基本操作,redis界面中输入`
help @set`即可查看。
这里只着重说一下几个命令
差集命令差集有左差右差,SDIFF k1 k2
,会找出k1中有,但k2中没有的元素,SDIFF k2 k1
会找出k2中有,但k1中没有的元素
随机的取出集合中一个或者多个元素。SRANDMEMBER k1 2
,随机取出k1中两个不重复的元素,SRANDMEMBER k1 -2
,随机取出k1中两个有可能重复的元素
首先清楚集合的特征:1. 无序;2.去重
那么如果你希望存重复的数据,set不适合;
set因为是无序的,所以也不会有下标访问,如果你希望访问指定元素,set也不适合。
SRANDMEMBER key 3
,就能从key这个set中,取出3个不重复的元素,SRANDMEMBER key -3
会取出3个有可能重复的元素。因此跟随机有关的场景,可以考虑一下set,例如抽奖。参考《redis设计与实现》
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。