Redis-对象

参考资料 极客时间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;// 是整数,直接添加元素到setsubject->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 {// 不是整数,直接转为HTsetTypeConvert(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转为DicthashTypeTryConversion(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)// 查找keyrobj *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,则转为HTif (len > server.hash_max_ziplist_value) {hashTypeConvert(o, OBJ_ENCODING_HT)return;}sum += len;}// ziplist⼤⼩超过1G,也转为HTif (!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不为空,开始查找keyfptr = ziplistFind(zl, fptr, (unsigned char*) field, sdslen(value));if (fptr != NULL){//判断是否存在,如果已经存在则更新update=1;ziplistReplace(zl, vptr, (unsigned char*) value,sdslen (value))// 不存在,则直接pushif(!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.mzph.cn/news/230016.shtml

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

相关文章

2023年国家基地“楚慧杯”网络空间安全实践能力竞赛 Wp 一点WP

MISC 参考文章&#xff1a; 天权信安“”2023年国家基地“楚慧杯”网络安全实践能力竞赛初赛WriteUp ez-zip 使用脚本解套娃压缩包 import io import zipfilewith open("4096.zip", "rb") as f:data f.read()info "666"while True:with zi…

AttributeError: module ‘jax‘ has no attribute ‘Array‘解决方案

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

【梅西迭代姊妹篇2】BCH码和m序列参数估计(梅西迭代算法求多项式的C语言实现)

伯利坎普迭代算法解决了BCH码译码中求错位多项式 σ ( x ) \sigma (x) σ(x)的问题,即用迭代算法求解方程组,极大地加快了译码速度。求最短线性移存器的迭代算法是梅西(J.Massey)于1969年提出的,而且指出了与BCH码迭代译码算法之间的关系,即求最短线性移存器的迭代算法实…

Linux——Ubuntu搭建FTP 时ftp: connect: Connection refused

如何解决ftp: connect: Connection refused&#xff1f; 分析&#xff1a;vsftpd.conf配置文件中默认ipv4:listenNO,ipv6:listen_ipv6YES,默认使用ipv6地址 解决方法&#xff1a;在配置文件中将listenYES开启&#xff0c;并且把listen_ipv6YES注释&#xff0c;重新启动vsftpd…

金蝶云星空和聚水潭单据接口对接

金蝶云星空和聚水潭单据接口对接 接入系统&#xff1a;聚水潭 聚水潭SaaSERP于2014年4月上线&#xff0c;目前累计超过2.5万商家注册使用&#xff0c;成为淘宝应用服务市场ERP类目商家数和商家月订单增速最快的ERP。2014年及2015年“双十一”当天&#xff0c;聚水潭SaaSERP平稳…

初识迭代器(Iterator)——迭代器模式——迭代加深(后续更新...)

学习网页&#xff1a; Welcome to Python.orghttps://www.python.org/ 迭代器&#xff08;Iterator&#xff09; 迭代器是一个非常有用的Python特性&#xff0c;它允许我们遍历一个容器&#xff08;如列表、元组、字典、集合等&#xff09;的元素。迭代器提供了一种方法&…

Vue中的数据变化监控与响应——深入理解Watchers

目录 ​编辑 前言 1. 基本用法&#xff1a; 2. 深度监听&#xff1a; 3. 立即执行&#xff1a; 4. 监听多个数据&#xff1a; 5. 清理监听器&#xff1a; 6. 监听路由变化&#xff1a; 总结&#xff1a; 我的其他博客 前言 在Vue.js中&#xff0c;watch是一种用于监听…

Kafka本地安装⭐️(Windows)并测试生产消息以及消费消息的可用性

2023.12.17 天气晴 温度较低 十点半&#xff0c;不是不想起实在是阳光浴太nice了日常三连&#xff0c;喂&#xff0c;刷&#xff0c;肝刷会儿博客&#xff0c;看会儿设计模式冷冷冷 进被窝 刷视频 睡觉看看kafka的本地部署 》》实践》》成功写会儿博客&#xff0c…

【mysql】ACID靠什么保证的呢?

回答: A 原子性:由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql undo log: 我们在进行数据更新操作的时候,不仅会记录redo log,还会记录undo log,如果因为某些原因导致事务回滚,那么这个时候MySQL就要执行回滚(rollback)操作,利用…

Web前端-HTML(表格与表单)

文章目录 1.表格与表单1.1 概述 2.表格 table2.1 表格概述2.2. 创建表格2.3 表格属性2.4. 表头单元格标签th2.5 表格标题caption&#xff08;了解&#xff09;2.6 合并单元格(难点)2.7 总结表格 3. 表单标签(重点)3.1 概述3.2 form表单3.3 input 控件(重点)type 属性value属性值…

useEffect 的第二个参数, 传空数组和传依赖数组有什么区别?

在 React 的 useEffect 钩子函数中&#xff0c;第二个参数用于指定依赖项数组。这个参数可以影响 useEffect 的触发时机和频率。 当传递空数组 [] 作为第二个参数时&#xff1a; useEffect 只会在组件初始化渲染完成后执行一次&#xff0c;相当于 componentDidMount。 它不会再…

Android 蓝牙BluetoothAdapter 相关(一)

Android 蓝牙相关 本文主要讲述android 蓝牙的简单使用. 1: 是否支持蓝牙 /*** 是否支持蓝牙** return*/ private boolean isSupportBluetooth() {BluetoothAdapter bluetoothAdapter BluetoothAdapter.getDefaultAdapter();return bluetoothAdapter ! null; }2: 开启蓝牙 …

Java之Clonable接口和深浅拷贝

Clonable接口 我们船舰了一个人的对象&#xff0c;想要克隆一个一模一样的对象&#xff0c;可以用到object类里面的克隆方法 object不是所有类的父类吗&#xff1f;那为什么用person1点不出这个方法呢&#xff1f;可以看一下源码 这是Object类里面的clone方法的声明&#xff0…

HackTheBox-Machines--Analytics

文章目录 1 端口扫描2 测试思路3 漏洞探测4 权限获取5 权限提升 Analytics 测试过程 1 端口扫描 nmap -sC -sV 10.129.205.1422 测试思路 目标服务器只开启了80端口&#xff0c;所以出发点从80端口开始。对于web页面&#xff0c;能做的大致思路有&#xff1a; 1.目录扫描   2…

干货下载丨不分业态、不关注核心需求,怎么做得好项目管理?!

项目管理&#xff1a;装备制造业的破局利刃 对于装备制造行业而言&#xff0c;每一笔订单都是非标定制、小批量制造。这种特性决定了其行业企业普遍存在新品开发周期长、生产效率低、质量不稳定、交货期不稳定、成本预算难控制、非标品报价慢等问题。 如何提升企业的管理水平…

【Java JVM】实例对象的创建

当我们涉及 Java 编程时, 对象的创建是一个基础而关键的概念。在 Java 中, 一切皆为对象, 而对象的创建方式直接影响代码的结构和性能。 本博客将探讨一下 Java 实例对象的创建过程。 1 创建对象的方法有哪些 在 Java 中如果要创建一个对象, 有哪些方式呢? 运用 new 关键字创…

国产or进口?台阶仪为何要选择国产

在微观轮廓测量领域&#xff0c;选择一款合适的台阶仪对于获得精准的测量结果至关重要。随着科技的不断发展&#xff0c;台阶仪市场上涌现了许多国产和进口产品&#xff0c;消费者在选择时可能会面临一些疑虑。 什么是台阶仪 台阶仪是一种超精密接触式微观轮廓测量仪&#xf…

JavaWeb文件上传与下载

一.文件上传 1. 引入两个jar包 jar包可以在maven库进行下载&#xff0c;地址&#xff1a;https://mvnrepository.com,一般点击下载量最多的jar进行下载就可以了。 apache:commons-fileupload.jarcommons-fileupload.jar这个jar包是依赖commons-io.jar的 2. 代码 前端代码&…

桌面概率长按键盘无法连续输入问题

问题描述&#xff1a;概率性长按键盘无法连续输入文本 问题定位&#xff1a; 系统按键流程分析 图一 系统按键流程 按键是由X Server接收的&#xff0c;这一点只要明白了X Window的工作机制就不难理解了。X Server在接收到按键后&#xff0c;会转发到相应程序的窗口中。在窗…

重启docker容器后,ssh无法访问且浏览器无法访问

今天把云服务器中的docker容器重启一遍后&#xff0c;发现里面的项目访问不到了&#xff0c;而且也无法ssh访问。 改了一天&#xff0c;终于还是改好了。 一 .首先是无法ssh访问&#xff0c; 我无法ssh连接的原因是因为我容器的重启之后sshd没有了&#xff0c;然后重新下载了…