Redis-对象

news2024/12/23 18:05:54

参考资料 极客时间Redis(亚风)

Redis对象

String

• 基本编码⽅式是RAW,基于简单动态字符串(SDS)实现,存储上限为512mb。
• 如果存储的SDS⻓度⼩于44字节,则会采⽤EMBSTR编码,此时object head与SDS是⼀段连续空间。申请内存时只需要调⽤⼀次内存分配函数,效率更⾼。
• 如果存储的字符串是整数值,并且⼤⼩在LONG_MAX范围内,则会采⽤INT编码:直接将数据保存在RedisObject的ptr指针位置(刚好8字节),不再需要SDS了。
对应第一种情况:
在这里插入图片描述
对应第二种情况:
在这里插入图片描述
对应第三种情况:
在这里插入图片描述

List

Redis采⽤QuickList实现List。

在这里插入图片描述

Set

Set是Redis中的集合,不⼀定确保元素有序,可以满⾜元素唯⼀、查询效率要求极⾼。
为了查询效率和唯⼀性,set采⽤HT编码(Dict)。Dict中的key⽤来存储元素,value统⼀为null.
当存储的所有数据都是整数,并且元素数量不超过set-max-intset-entries时,Set会采⽤lntSet编码,以节省内存。
第一中情况都是int类型:IntSet 实现

在这里插入图片描述
第二种:使用dict实现
在这里插入图片描述
上面过程对应的源码:

int setTypeAdd (robj *subject, sds value) {
	Long Long llval;
	if (subject->encoding==OBJ_ENCODING_HT) { 
	//已经是HT编码,直接添加元素
	dict *ht = subject->ptr;
	dictEntry *de = dictAddRaw(ht,value,NULL)if (de) {
	dictSetKey(ht, de, sdsdup (value))dictSetVal(ht,de, NULL)return 1 ; }
	}
	else if (subject->encoding == OBJ_ENCODING_INTSET){ 
	// ⽬前是INTSET
	// 判断value是否是整数
	if (isSdsRepresentableAsLongLong(value,&llval) == C_OK) {
	uint8_t success = 0;
	// 是整数,直接添加元素到set
	subject->ptr=intsetAdd (subject->ptr, llval, &success)if (success){
	/* 当intset元素数量超出set_max_intset_entries,则转为HT.*/
	size_t max_entries = server.set_max_intset_entries;
	if (max_entries >= 1<<30) max_entries=1<<30;
	if (intsetLen(subject->ptr) > max_entries)
	setTypeConvert(subject,OBJ_ENCODING_HT)return 1;
	}
	) else {
	// 不是整数,直接转为HT
	setTypeConvert(subject,OBJ_ENCODING_HT)serverAssert(dictAdd(subject->ptr,sdsdup (value),NULL)== DICT_OK)return 1;}
} }
ZSet

底层是用三种数据结构实现的(HT + SkipList + ZPlist)

typedef struct zset {
	// Dict指针
	dict *dict;
	// SkipList指针
	zskiplist *zsl;
} zset;

当元素数量不多时,HT和SkipList的优势不明显,⽽且更耗内存。因此zset还会采⽤ZipList结构来节省内存,不过需要同时满⾜两个条件:
① 元素数量⼩于zset-max-ziplist-entries,默认值128
② 每个元素都⼩于zset-max-ziplist-value字节,默认值64
源码如下:

// zadd添加元素时,先根据key找到zset,不存在则创建新的zset
zobj = LookupKeywrite(c->db, key)if (checkType (c, zobj,OBJ_ZSET)goto cleanup;
//判断是否存在
if (zobj == NULL) {// zset不存在
if (server.zset_max_ziplist_entries == 0
server.zset_max_ziplist_value < sdslen(c->argv [scoreidx+1]->ptr))
{ 
// zset_max_ziplist_entries设置为0就是禁⽤了ZipList,
//或者value⼤⼩超过了zset_max_ziplist_value,采⽤HT + SkipList
Zobj = createzsetobject()} else {
// 否则,采⽤ ZipList
zobj = createzsetziplistobject()}
dbAdd(c->db, key, zobj)}
zsetAdd(zobj,score, ele, flags, &retflags, &newscore)

Ziplist本身没有排序功能,⽽且没有键值对的概念,因此需要有zset通过编码实现:
• Ziplist是连续内存,因此score和element是紧挨在⼀起的两个entry,element在前,score在后
• score越⼩越接近队⾸,score越⼤越接近队尾,按照score值升序排列
在这里插入图片描述

Hash

Hash底层采⽤的编码与Zset也基本⼀致,只需要把排序有关的SkipList去掉即可:
• Hash结构默认采⽤ZipList编码,⽤以节省内存。Ziplist中相邻的两个entry 分别保存field和value
• 当数据量较⼤时,Hash结构会转为HT编码,也就是Dict,触发条件有两个:
① ZipList中的元素数量超过了hash-max-ziplist-entries(默认512)
② ZipList中的任意entry⼤⼩超过了hash-max-ziplist-value(默认64字节)
在这里插入图片描述

// 插入命令
void hsetCommand(client *c) {
	int i, created = 0;
	robj *o;
	//判断hash的key是否存在,不存在则创建⼀个新的,默认采⽤ZipList编码
	if ((o = hashTypeLookupwriteOrCreate(c, c->argv[1]))==NULL) return;
	// 判断是否需要把ZipList转为Dict
	hashTypeTryConversion(o,c->argv,2,c->argc-1)// 循环遍历每⼀对field和value,井执⾏hset命令
	for (i = 2;i<c-argc; i += 2)
	created += !hashTypeSet(o,c->argv[I]->ptr,c->argv[i+1]->ptr, HASH_SET_COPY);
	}
	robj *hashTypeLookupwriteOrCreate(client *c, robj *key)
	// 查找key
	robj *o = LookupKeywrite(c->db, key)if (checkType(c,o, OBJ_HASH)return NULL;
	// 不存在,则创建新的
	if (o == NULL) {
	o = createHashobject()dbAdd (c->db, key,o)}
	return o;
}
robj *createHashobject (void) {
	// 默认采⽤zipList编码,申请ZipList内存空间
	unsigned char *z1 = ziplistNew();
	robj *o = createobject(OBJ_HASH, z1)//设置编码
	o->encoding = OBJ_ ENCODING_ZIPLIST;
	return 0;
}
// ziplist 在什么时候转换为HT
void hashTypeTryConversion(robj *o,robj **argv, int start, int end)
	int i;size_t sum = 0;
	// 本来就不是ZipList编码,什么都不⽤做了
	if (o->encoding != OBJ_ENCODING_ZIPLIST) return;
	//依次遍历命令中的field、 value参数
	for (i = s. start; i < c. end;j++)
	if (!sdsEncodedobject (argv[i]))
	continue;
	size_t len = sdsLen (argv[i]->ptr)// 如果field或value超过hash_max_ziplist_value,则转为HT
	if (len > server.hash_max_ziplist_value) {
	hashTypeConvert(o, OBJ_ENCODING_HT)return;
	}
	sum += len;
	}
	// ziplist⼤⼩超过1G,也转为HT
	if (!ziplistSafeToAdd(o- >ptr, sum))
	hashTypeConvert(o, OBJ_ENCODING_HT)}
// 真正插入元素的逻辑
int hashTypeSet(robj *o,sds field, sds value, int flags){
	int update = 0// 判断是否为ZipList编码
	if (o->encoding == OBJ_ENCODING_ZIPLIST) {
	unsigned char *zl, *fptr, *vptr;
	zl = o->ptr;
	// 查询head指针
	fptr = ziplistIndex(zl, ZIPLIST_HEAD)if (fptr != NULL)// head不为空,说明ZipList不为空,开始查找key
	fptr = ziplistFind(zl, fptr, (unsigned char*) field, sdslen(value));
	if (fptr != NULL){//判断是否存在,如果已经存在则更新
	update=1;
	ziplistReplace(zl, vptr, (unsigned char*) value,sdslen (value))// 不存在,则直接push
	if(!update){ // 依次push新的field和value到zipList的尾部
	zl = ziplistPush(zl, (unsigned char*) field, sdslen(field),ZIPLIST_TAIL);
	zl = ziplistPush(zl, (unsigned char*)value, sdslen (value),ZIPLIST_TAIL)}
	o->ptr = zl;
	/* 插⼊了新元素,检查list⻓度是否超出,超出则转为HT */
	if (hashTypeLength(o)>server.hash_max_ziplist_entries)
	hashTypeConvert(o, OBJ_ENCODING_HT)} else if (o->encoding == OBJ_ENCODING_HT) {
	// HT编码,直接插⼊或覆盖
	} 
	return update;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1317622.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QT:Unable to create a debugging engine.

debug跑不了&#xff1a; 报错&#xff1a;Unable to create a debugging engine. 参考&#xff1a; https://blog.csdn.net/u010906468/article/details/104716198 先检查是否安装了DEBUG插件 工具-》》选项 查看插件&#xff0c;如果没有的话&#xff0c;需要重新安装qt时…

计算机操作系统-第十七天

目录 处理机调度 调度的基本概念 作业 高级调度&#xff08;作业调度&#xff09; 中级调度&#xff08;内存调度&#xff09; 低级调度&#xff08;进程调度/处理机调度&#xff09; 进程的挂起态与七状态模型 挂起和阻塞的区别 三层调度的联系和对比 本节思维导图…

SDN控制器-ONOS中的最终一致性存储

ONOS中的数据存储基本上都是以KV进行存储的。按照一致性强弱类型可以分为强一致性存储&#xff08;strong consistency&#xff09;与弱一致性存储&#xff08;eventually consistency&#xff09;。 比较典型的&#xff0c;如ONOS中对于设备接口的存储&#xff0c;使用的是强…

XXE漏洞 [NCTF2019]Fake XML cookbook1

打开题目 查看源代码 发现我们post传入的数据都被放到了doLogin.php下面 访问一下看看 提示加载外部xml实体 bp抓包一下看看 得到flag 或者这样 但是很明显这样是不行的&#xff0c;因为资源是在admin上&#xff0c;也就是用户名那里 PHP引用外部实体&#xff0c;常见的利用…

【23-24 秋学期】NNDL 作业11 LSTM

目录 习题6-4 推导LSTM网络中参数的梯度&#xff0c; 并分析其避免梯度消失的效果 习题6-3P 编程实现下图LSTM运行过程 &#xff08;一&#xff09;numpy实现 &#xff08;二&#xff09;使用nn.LSTMCell实现 &#xff08;三&#xff09; 使用nn.LSTM实现 总结 &#x…

PMI相关证书的获取步骤及注意内容

近几年很多行业的从业人员都在考取PMI项目管理相关证书&#xff0c;可在中国大陆地区参加考试的认证主要有&#xff1a;PMP, PgMP, PMI-RMP, PMI-ACP, PMI-PBA, CAPM。PfMP, PMI-SP尚未在中国大陆地区开放考试。 现整理该类证书的相关获取步骤及注意内容 一、证书获取步骤 S…

动态规划(Dynamic Programming)

动态规划&#xff08;Dynamic Programming&#xff09;&#xff1a;是运筹学的一种最优化方法&#xff0c;只不过在计算机问题上应用比较多 DP常见步骤&#xff1a; 暴力递归/穷举记忆化搜索&#xff08;傻缓存 递归&#xff09;,使用备忘录/ DP Table 来优化穷举过程严格表结…

锁--07_2---- index merge(索引合并)引起的死锁

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 案例分析生产背景死锁日志表结构执行计划 EXPLAN为什么会用 index_merge&#xff08;索引合并&#xff09;为什么用了 index_merge就死锁了解决方案注&#xff1a;M…

SQL基础:操作环境搭建

在上一节中&#xff0c;我们简单讲述了数据库和SQL的基本概念。 本节我们讲述一下环境搭建&#xff0c;为下一节讲表的基本操作做下铺垫。 环境搭建 具体到操作&#xff0c;我们就要准备一些环境了。如果不进行练习&#xff0c;我们学习的知识将很快被遗忘。 MySQL安装&…

如何使用Lychee结合内网穿透搭建本地私人图床网站并实现远程访问

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 图床作为图片集中存放的服务网站&#xff0c;可以看做是云存储的一部分&#xff0c;既可…

四舍五入浮点数

1.题目如下&#xff1a; 2.方法一&#xff1a; 直接取出小数部分第一位来判断。 1. 先乘以10。 2. 强制类型转换为整型&#xff0c;去掉小数部分。 3. 再模10&#xff0c;相当于取出原数的小数第一位。 代码实现&#xff1a; int way1(double n) {int a (int)(n * 10);int b…

kafka学习笔记--Kafka副本

本文内容来自尚硅谷B站公开教学视频&#xff0c;仅做个人总结、学习、复习使用&#xff0c;任何对此文章的引用&#xff0c;应当说明源出处为尚硅谷&#xff0c;不得用于商业用途。 如有侵权、联系速删 视频教程链接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;从入门到调优…

一些关于fMRI脑数据的预处理工具

一些关于fMRI脑数据的预处理工具 前言概述SPM12工具箱FSL工具箱FreeSurfer工具箱BrainNet Viewer工具箱circularGraph工具箱Nipype集成框架fMRIPrep集成框架参考文献 前言 March 25, 2022 这里是关于fMRI脑数据的预处理工具的相关调研 主要是关于数据的预处理&#xff0c;数据…

万兆网络之屏蔽线序接法(中)

在介绍优质网线选购之前&#xff0c;先简单介绍一下水晶头 1毛钱一颗跟1元一颗的水晶头&#xff0c;往往是金手指厚度差别&#xff0c;你可以想象压制的时候可能会有什么情况 另外&#xff0c;一些3元一颗的镀金水晶头会有15U、30U之类的是电镀厚度单位&#xff0c;数值越大镀…

【数据挖掘】国科大苏桂平老师数据库新技术课程作业 —— 第四次作业

云数据库研究 云计算与云数据库背景 云计算&#xff08;cloud computing&#xff09;是 IT 技术发展的最新趋势&#xff0c;正受到业界和学术界的广泛关注。云计算是在分布式处理、并行处理和网格计算等技术的基础上发展起来的&#xff0c;是一种新兴的共享基础架构的方法。它…

java内置的数据结构

Java语言提供了许多内置的数据结构&#xff0c;包括&#xff1a; 1. 数组&#xff08;Array&#xff09;&#xff1a;数组是最基本的数据结构之一&#xff0c;它是一个有序的元素集合&#xff0c;每个元素都有一个对应的索引。在Java中&#xff0c;数组可以通过声明和初始化来创…

2023年金属非金属矿山(地下矿山)安全管理人员证模拟考试题库及金属非金属矿山(地下矿山)安全管理人员理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员证模拟考试题库及金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员理论考试试题是由安全生产模拟考试一点通提供&#xff0c;金属非金…

《软件方法(下)》第8章2023版8.1 分析工作流概述

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 第8章 分析 之 分析类图——知识篇 墙上挂了根长藤&#xff0c;长藤上面挂铜铃 《长藤挂铜铃》&#xff1b;词&#xff1a;元庸&#xff0c;曲&#xff1a;梅翁&#xff08;姚敏&…

手麻、腿麻、麻痛…背后竟隐藏7大疾病!多一个人知道,少一个悲剧!

手脚麻木背后的7大病症&#xff1a;骨病、脑梗、肿瘤…… 1、神经问题 上图四只手上橙色的区域代表了麻木感&#xff0c;如果您的手麻集中在无名指和小指的区域&#xff0c;您可以拿一张纸&#xff0c;用五个手指分别试着夹住&#xff0c;检验您的五个手指力量&#xff1b;您还…

软件测试之鲁棒性测试

文章目录 前言一、鲁棒性测试是什么&#xff1f;二、鲁棒性测试的目的三、测试原理3.1 错误数据处理3.2 异常情况处理 前言 Bootloader软件刷写鲁棒性(Robustness)测试是指对Bootloader软件进行连续多次的刷写测试&#xff0c;且一次Fail都没发生&#xff0c;以此验证Bootload…