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博客专家、人工智能领域优质创作者。…

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…

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属性值…

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;每一笔订单都是非标定制、小批量制造。这种特性决定了其行业企业普遍存在新品开发周期长、生产效率低、质量不稳定、交货期不稳定、成本预算难控制、非标品报价慢等问题。 如何提升企业的管理水平…

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

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

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

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

助力智能人群检测计数,基于YOLOv5全系列模型【n/s/m/l/x】开发构建通用场景下人群检测计数识别系统

在一些人流量比较大的场合&#xff0c;或者是一些特殊时刻、时段、节假日等特殊时期下&#xff0c;密切关注当前系统所承载的人流量是十分必要的&#xff0c;对于超出系统负荷容量的情况做到及时预警对于管理团队来说是保障人员安全的重要手段&#xff0c;本文的主要目的是想要…

SpringIOC之作用域Scope

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

设计模式之创建型设计模式(一):单例模式 原型模式

单例模式 Singleton 1、什么是单例模式 在软件设计中&#xff0c;单例模式是一种创建型设计模式&#xff0c;其主要目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 这意味着无论何时需要该类的实例&#xff0c;都可以获得相同的实例&#xff0c;而不会创建…

使用VBA快速统计词组词频(多单词组合)(2/2)

实例需求&#xff1a;产品清单如A列所示&#xff0c;现在如下统计多单词组合词组词频。 在上一篇博客中《使用VBA快速统计词组词频(多单词组合)&#xff08;1/2&#xff09;》讲解了如何实现双词的词频统计。 本文将讲解如何实现3词的词频统计&#xff0c;掌握实现方法之后&a…

Mac如何安装stable diffusion

今天跟大家一起在Mac电脑上安装下stable diffusion&#xff0c;在midjourney等模型收费的情况下如何用自己的电脑算力用上免费的画图大模型呢&#xff1f;来吧一起实操起来 一、安装homebrew 官网地址&#xff1a;Homebrew — The Missing Package Manager for macOS (or Lin…

SQL进阶理论篇(十):数据库中的锁

文章目录 简介按照锁的粒度进行划分从数据库管理的角度进行划分从程序员的角度进行划分为什么共享锁会发生死锁&#xff1f;参考文献 简介 索引和锁&#xff0c;是数据库中的两个核心知识点。 索引的相关知识点&#xff0c;在之前的几章里我们已经介绍的差不多了。接下来我们…