Redis源码-Set:Redis Set存储原理、Redis Set集合操作命令、Redis Set两种存储底层编码intset+hashtable、Redis Set应用场景

Redis数据类型

Redis数据类型不等同与数据结构,数据结构是Redis该数据类型存储结构的存储原理,也是该数据类型的底层编码。

1.Set存储原理

请添加图片描述

Redis Set存储的是无序的字符串(String和Hash也是无序的,List和zset是有序的),元素不能重复。
最大存储数量2^32-1(40亿左右元素数量)。

列表list、集合set、有序集合zset差异

数据结构是否允许重复元素是否有序有序实现方式
列表list索引下标
集合set-
有序集合zset分值score

2.1Redis-Set数据类型:操作命令

Set的命令都是前面+s开头的。

放入集合多个元素

# sadd key member [member ...]:放入集合多个元素,返回集合大小
127.0.0.1:6379> sadd myset aa bb cc dd
(integer) 4

查看集合元素内容

# smembers key:查看集合元素内容
127.0.0.1:6379> smembers myset
1) "dd"
2) "bb"
3) "aa"
4) "cc"

统计集合元素个数

# scard key
127.0.0.1:6379> scard myset
(integer) 4

随机获取集合的元素

# srandmember key [count]:随机获取集合的元素,count为随机获取的个数,默认1
127.0.0.1:6379> srandmember myset
"bb"
127.0.0.1:6379> srandmember myset 2
1) "bb"
2) "dd"

弹出集合的元素(无序的,因此是随机弹,也是删除)

# spop key [count]:弹出集合的元素(无序的,因此是随机弹,也是删除),count为随机获取的个数,默认1
127.0.0.1:6379> spop myset
"aa"
127.0.0.1:6379> spop myset 2
1) "cc"
2) "dd"

删除指定的元素

# srem key member [member ...]:多个元素空格隔开
# 返回删除成功的个数
127.0.0.1:6379> sadd myset aa bb jj kk ll
(integer) 5
127.0.0.1:6379> srem myset aa bb oo
(integer) 2

判断集合是否存在元素

#  sismember key member:判断集合是否存在元素,存在返回1,不存在返回0
127.0.0.1:6379> sismember myset jj
(integer) 1
127.0.0.1:6379> sismember myset 99
(integer) 0

2.2Redis-Set数据类型:集合操作命令(差集、并集、交集)

set1{a,b,c} set2{c,d,e}

获取差集:
sdiff set1 set2 {a,b,d,e}
获取交集:(intersection)
sinter set1 set2 {c}
获取并集:
sunion set1 set2 {a,b,c,d,e}

查看Redis内部的数据结构类型

当你插入Redis一个字符串数据时,会根据你插入的值,Redis再进行内部的数据转换。
可以先看本文目录:3.存储原理(底层编码)

可以用object encoding key名查看key的value再Redis的内部数据类型。

# 查看key在Redis的对内数据类型
127.0.0.1:6379> object encoding myset
"hashtable"

3.存储原理(底层编码)

Redis源码:Redis源码怎么查看入门、Redis外部数据结构到Redis内部数据结构查看源码顺序、Redis源码查看顺序

Redis Set两种底层编码类型:intset、hashtable

Redis Set类型的内部底层编码有两种:

根据存储内容的不同大小采取合适的编码,从而达到更好的效果

  1. intset,存储纯数字的情况下才会用到
  2. hashtable,OBJ_ENCODING_HT(哈希表,和Redis外层的Hash是一个)

Redis Set底层编码类型①:intset

intset编码只有存储纯数字的情况下才会用到

在这里插入图片描述

intset.h源码文件

intset.h源码文件在解压后的src目录下

typedef struct intset {
    uint32_t encoding;		// 编码类型 int_16t、int_32t、int_64t、
    uint32_t length;		// 长度 最大长度2^32 (40亿左右)
    int8_t contents[];		// 用来存储成员的动态数组
} intset;

Redis Set底层编码类型②:hashtable

首先需要搞明白Redis外层的Hash表是什么。
Redis中的Hash结构,在Redis中,所有的KV存储方式都是基于dict(外层Hash表,HashTable)这个结构去存存储的,那么如果value的编码类型也是hashtable,应该怎么存储,其实就是hashtable的嵌套结构。
不理解dict结构、外层Hash、dict、dictht、dictEntry可以去看:
Redis源码:Redis源码怎么查看、Redis源码查看顺序、Redis外部数据结构到Redis内部数据结构查看源码顺序、Redis KV存储方式都是基于dict

Redis的KV存储方式-dict、dictht、dictEntry关系图

在Redis中,所有的KV存储方式都是基于dict(外层Hash表,HashTable)这个结构去存储的。
外层的KV存储的HashTable(dict),结构如下
请添加图片描述

Redis 底层编码类型hashtable嵌套结构图

总体存储结构为:【dictEntry有序链表】→【放在dictEntry数组里面】→【dictEntry数组放在dictht(哈希表ht[0])里面】→【dictht又放在dict结构里面】
请添加图片描述

Hash的扩容

扩容怎么扩容的?
判断的条件:
扩容比例(源码dict.c中定义):
在这里插入图片描述

static unsigned int dict_force_resize_ratio = 5;	/*
													dictEntry数组后面的dictEntry链表,
													所有节点的链表平均值超过一定程度(会计算dictEntry链表长度和dictEntry的长度的比例,这个值为5),
													也就表示hash碰撞很严重,就会触发扩容。
													*/

dictEntry数组后面的dictEntry链表,所有节点的链表平均值超过一定程度(会计算dictEntry链表长度和dictEntry的长度的比例,源码中这个值为5),也就表示hash碰撞很严重,就会触发扩容。

扩容的量级是原dictht的2的n次方,扩容之后,会把原表的数据重新分配到新表(rehash,重新计算hash),然后用ht[0]标记为当前使用的是哪个表,清空原先的dictht来释放空间。

4.应用场景

  • 抽奖:spop myset
  • 唯一性记录:点赞、签到、打卡(用户记录)
  • 商品标签、用户画像(人口属性、信用属性、社交、爱好…)
  • 用户关注、推荐模型
  • 基于集合的商品类别筛选

唯一性记录:点赞、签到、打卡(用户记录)

即用被点赞的记录作为key,用户作为set 的value进行维护。商品标签也是同样的道理。

用key(zan:v1001)来维护这条记录的所有点赞用户
用户u0001的点赞了这个记录:sadd zan:v1001 u0001
用户u0001的取消点赞这个记录:srem zan:v1001 u0001
用户u0001是否点赞了这个记录:sismember zan:v1001 u0001
这个记录点赞的所有用户:smembers zan:v1001
这个记录总点赞数:scard zan:v1001

基于集合的商品类别筛选

在这里插入图片描述

搜一款手机筛选条件如下:品牌ROG、机身内存1TB、CPU型号骁龙8+ Gen 1
可以用Redis set来实现

# sadd key (brand:ROG) value 该品牌手机型号
sadd brand:ROG ROG5s ROG6 ROG6pro ROG2 ROG3
# sadd key (cpud的分类key:cpu:8+Gen1) value 手机型号
sadd cpu:8+Gen1 ROG6 ROG6pro
sadd cpu:888 ROG5
# sadd key (ram的分类key:ram:1TB) value 手机型号
sadd ram:1TB ROG6 ROG6pro

# 搜一款手机筛选条件如下:品牌ROG、机身内存1TB、CPU型号骁龙8+ Gen 1
sinter brand:ROG cpu:8+Gen1 ram:1TB

Redis各数据结构命令、源码分析、应用场景

Redis源码-String:Redis String命令、Redis String存储原理、Redis String三种编码类型、Redis字符串SDS源码解析、Redis String应用场景

Redis源码-Hash:Redis String与Hash的区别、Redis Hash存储原理、Redis Hash命令、 Redis Hash存储底层编码、Redis Hash应用场景

Redis源码-List:Redis List存储原理、Redis List命令、 Redis List存储底层编码quicklist、Redis List应用场景

Redis源码-Set:Redis Set存储原理、Redis Set集合操作命令、Redis Set两种存储底层编码intset+hashtable、Redis Set应用场景

Redis源码-ZSet:Redis ZSet存储原理、Redis ZSet命令、 Redis ZSet两种存储底层编码ziplist/dict+skiplist、Redis ZSet应用场景

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值