- 存储类型与操作命令
| 类型(Type key) | 存储编码(OBJECT encoding key) | 实例命令 |
|---|---|---|
| set | inset | sadd myset1 11 23 54 66 |
| set | hashtable | sadd myset a b c d e f |
问题:Redis是如何决定存储inset还是hashtable?
答:在Redis配置文件有一个叫set-max-inset-entries的属性(默认512)其意义是inset集合中的元素都是整数且元素个数小于set-max-inset-entries配置(默认512)个数,redis会选用它来减少内存的使用,若无法满足intset条件时(如实际超过512个)hashtable作为内部实现
存储原理
- inset
typedef struct intset {
uint32_t encoding;//编码类型 int16_t int32_t int64_t
uint32_t length;//元素个数 最大长度:2的32次幂
int8_t contents[];//柔性数组,根据encoding字段决定几个字节表示一个元素
} intset
- 结构示意图
- encoding
encoding:编码类型,决定每个元素占用几个字节。有如下3种类型。
1.INTSET_ENC_INT16:当元素值都位于INT16_MIN和INT16_MAX之间时使用。 该编码方式为每个元素占用2个字节。
2.INTSET_ENC_INT32:当元素值位于INT16_MAX到INT32_MAX或者INT32_MIN到INT16_MIN之间时使用。该编码方式为每个元素占用4个字节。
3.INTSET_ENC_INT64:当元素值位于INT32_MAX到INT64_MAX或者INT64_MIN到INT32_MIN之间时使用。该编码方式为每个元素占用8个字节
判断一个值需要什么类型的编码格式,只需要查看该值所处的范围即可:
| 编码 | 值 |
|---|---|
| INTSET_ENC_INT16 | [-32768,32767] |
| INTSET_ENC_INT32 | (32767,2147483647)或[-2147483648,-32768] |
| INTSET_ENC_INT64 | (2147483647,9223372036854775807)或[-9223372036854775808,-2147483648] |
根据encoding属性扩容:
intset结构体会根据待插入的值决定是否需要进行扩容操作。扩容会修改encoding字 段,而encoding字段决定了一个元素在contents柔性数组中占用几个字节。所以当修改encoding字段之后,intset中原来的元素也需要在contents中进行相应的扩展,只要待插入的值导致了扩容,则该值在待插入的intset中不 是最大值就是最小值
//encoding字段在Redis中使用宏来表示,其定义如下:
define INTSET_ENC_INT16 (sizeof(int16_t))
define INTSET_ENC_INT32 (sizeof(int32_t))
define INTSET_ENC_INT64 (sizeof(int64_t))
编码类型
| 宏 | 值 |
|---|---|
| INTSET_ENC_INT16 | 2 |
| INTSET_ENC_INT32 | 4 |
| INTSET_ENC_INT64 | 8 |
因为encoding字段实际取值为2、4、8,所以encoding字段可以直接比较大小。当待插 入值的encoding字段大于待插入intset的encoding时,说明需要进行扩容操作,并且也能表 明该待插入值在该intset中肯定不存在。
应用场景
- 抽奖
- 点赞、签到、打卡(用户记录)
- 商品标签、用户画像(人口属性、信用属性、社交、兴趣爱好····)
- 用户关注、推荐模型