最新要闻
- 滚动:新金路(000510.SZ):提请股东大会授权董事局办理以简易程序向特定对象发行股票
- 英足总杯丨马赫雷斯“戴帽”,曼城挺进决赛|精选
- 让老外爱上“砍一刀”!拼多多Temu英国站已正式上线 天天亮点
- 每日播报!圆球停在斜坡顶端 网友称物理学不存在了 体彩中心:可能是天气原因
- 美国多个州要求召回韩国汽车:缺乏基本的防盗装置 危及公共安全
- 环球快消息!比亚迪百万豪车!仰望U8开车第一视角曝光:马路都感觉变窄了
- 蛋蛋面膜真的能去皱纹吗_蛋蛋面膜
- 亚香股份: 2022年年度报告摘要
- 全球速读:劳斯莱斯不让进展台 小姐姐直接买了仰望U8、仰望U9两款车
- 【时快讯】广州街头大众CC变道不成 倒车怒撞奔驰E 网友直呼太恶劣
- 华为宣布开放5G网络能力 自家5.5G比5G快10倍|焦点速读
- 什么是期货对冲交易 全球独家
- 每日观点:歌词那些遗憾留在心底_心中的遗憾歌词
- 当前观察:今日沈阳老凤祥黄金价格查询(2023年4月23日)
- 全球快播:提车时大风吹倒墙壁新车被砸 男子:4S店只修不换不退
- 【当前独家】抖音推出种草产品有柿App 由头条搜索升级而来
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
《Redis设计与实现》读书笔记 焦点简讯
《Redis设计与实现》读书笔记
简单动态字符串
SDS的定义
结构:
buf数组:用于保存字符串
len属性:记录SDS中保存字符串的长度
(资料图)
free属性:记录buf中未使用字节数量
遵循C字符串以空字符串结尾的惯例,保存空字符串的字节不计入长度
SDS与C字符串的区别
常数复杂度获取字符串长度
因为SDS中的len属性已经记录了字符串长度,所以不需要像C字符串一样获取长度时需要遍历一遍字符串。确保获取字符串长度的工作不会限制Redis的性能瓶颈
杜绝缓冲区溢出
当SDS API需要对SDS进行修改时,API会先检查SDS的空间是否满足修改所需要的要求,如果不满足的话,API会自动将SDS的空间扩展至执行修改所需要的大小
减少修改字符串时带来的内存重分配次数
C字符串修改时,需要程序重新分配内存,防止内存溢出或泄露。对于一个数据库来说吗,对于速度的要求时苛刻的,且数据会被频繁的修改。而重分配会占用大量时间,修改频繁的话,可能会对性能照成影响
而SDS通过free属性,实现了空间预分配与惰性空间释放两种优化策略
1.空间预分配
SDS进行修改后len小于1MB时:程序会分配和len相同大小的未使用空间
SDS进行修改后len大于1MB时:程序会分配1MB的未使用空间
2.惰性空间释放
当需要缩短SDS的字符串时,程序不会立刻重分配来回收多余字节,而是先使用free将这些字节记录起来,等待将来再使用
二进制安全
SDS API会以二进制的方式来处理SDS存放在数组里面的数据
兼容部分C字符串函数
因为SDS遵循了C字符串以空字符串结尾的惯例
SDS API
链表
链表与链表节点的实现
每个链表节点使用一个 adlist.h/listNode
结构来表示:
typedef struct listNode { // 前置节点 struct listNode *prev; // 后置节点 struct listNode *next; // 节点的值 void *value;} listNode;
多个 listNode
可以通过 prev
和 next
指针组成双端链表
虽然仅仅使用多个 listNode
结构就可以组成链表, 但使用 adlist.h/list
来持有链表的话, 操作起来会更方便:
typedef struct list { // 表头节点 listNode *head; // 表尾节点 listNode *tail; // 链表所包含的节点数量 unsigned long len; // 节点值复制函数 void *(*dup)(void *ptr); // 节点值释放函数 void (*free)(void *ptr); // 节点值对比函数 int (*match)(void *ptr, void *key);} list;
list
结构为链表提供了表头指针 head
、表尾指针 tail
, 以及链表长度计数器 len
, 而 dup
、 free
和 match
成员则是用于实现多态链表所需的类型特定函数:
dup
函数用于复制链表节点所保存的值;free
函数用于释放链表节点所保存的值;match
函数则用于对比链表节点所保存的值和另一个输入值是否相等。
Redis 的链表实现的特性可以总结如下:
双端: 链表节点带有
prev
和next
指针, 获取某个节点的前置节点和后置节点的复杂度都是 。无环: 表头节点的
prev
指针和表尾节点的next
指针都指向NULL
, 对链表的访问以NULL
为终点。带表头指针和表尾指针: 通过
list
结构的head
指针和tail
指针, 程序获取链表的表头节点和表尾节点的复杂度为 。带链表长度计数器: 程序使用
list
结构的len
属性来对list
持有的链表节点进行计数, 程序获取链表中节点数量的复杂度为 。多态: 链表节点使用
void*
指针来保存节点值, 并且可以通过list
结构的dup
、free
、match
三个属性为节点值设置类型特定函数, 所以链表可以用于保存各种不同类型的值。
链表和链表节点的API
字典
字典的实现
哈希表
Redis 字典所使用的哈希表由 dict.h/dictht
结构定义:
typedef struct dictht { // 哈希表数组 dictEntry **table; // 哈希表大小 unsigned long size; // 哈希表大小掩码,用于计算索引值 // 总是等于 size - 1 unsigned long sizemask; // 该哈希表已有节点的数量 unsigned long used;} dictht;
table
属性是一个数组, 数组中的每个元素都是一个指向 dict.h/dictEntry
结构的指针, 每个 dictEntry
结构保存着一个键值对。
size
属性记录了哈希表的大小, 也即是 table
数组的大小, 而 used
属性则记录了哈希表目前已有节点(键值对)的数量。
sizemask
属性的值总是等于 size - 1
, 这个属性和哈希值一起决定一个键应该被放到 table
数组的哪个索引上面。
哈希表节点
哈希表节点使用 dictEntry
结构表示, 每个 dictEntry
结构都保存着一个键值对:
typedef struct dictEntry { // 键 void *key; // 值 union { void *val; uint64_t u64; int64_t s64; } v; // 指向下个哈希表节点,形成链表 struct dictEntry *next;} dictEntry;
key
属性保存着键值对中的键, 而 v
属性则保存着键值对中的值, 其中键值对的值可以是一个指针, 或者是一个 uint64_t
整数, 又或者是一个 int64_t
整数。
next
属性是指向另一个哈希表节点的指针, 这个指针可以将多个哈希值相同的键值对连接在一次, 以此来解决键冲突(collision)的问题。
举个例子, 图 4-2 就展示了如何通过 next
指针, 将两个索引值相同的键 k1
和 k0
连接在一起。
字典
Redis 中的字典由 dict.h/dict
结构表示:
typedef struct dict { // 类型特定函数 dictType *type; // 私有数据 void *privdata; // 哈希表 dictht ht[2]; // rehash 索引 // 当 rehash 不在进行时,值为 -1 int rehashidx; /* rehashing not in progress if rehashidx == -1 */} dict;
type
属性和 privdata
属性是针对不同类型的键值对, 为创建多态字典而设置的:
type
属性是一个指向dictType
结构的指针, 每个dictType
结构保存了一簇用于操作特定类型键值对的函数, Redis 会为用途不同的字典设置不同的类型特定函数。而
privdata
属性则保存了需要传给那些类型特定函数的可选参数。
typedef struct dictType { // 计算哈希值的函数 unsigned int (*hashFunction)(const void *key); // 复制键的函数 void *(*keyDup)(void *privdata, const void *key); // 复制值的函数 void *(*valDup)(void *privdata, const void *obj); // 对比键的函数 int (*keyCompare)(void *privdata, const void *key1, const void *key2); // 销毁键的函数 void (*keyDestructor)(void *privdata, void *key); // 销毁值的函数 void (*valDestructor)(void *privdata, void *obj);} dictType;
ht
属性是一个包含两个项的数组, 数组中的每个项都是一个 dictht
哈希表, 一般情况下, 字典只使用 ht[0]
哈希表, ht[1]
哈希表只会在对 ht[0]
哈希表进行 rehash 时使用。
除了 ht[1]
之外, 另一个和 rehash 有关的属性就是 rehashidx
: 它记录了 rehash 目前的进度, 如果目前没有在进行 rehash , 那么它的值为 -1
。
哈希算法
将新的键值插入字典时,程序需要先根据键值对的键计算出哈希值和索引值,然后根据索引值将新键值对所在的哈希表节点放到哈希表数组对应的索引上面
Redis 计算哈希值和索引值的方法如下:
# 使用字典设置的哈希函数,计算键 key 的哈希值hash = dict->type->hashFunction(key);# 使用哈希表的 sizemask 属性和哈希值,计算出索引值# 根据情况不同, ht[x] 可以是 ht[0] 或者 ht[1]index = hash & dict->ht[x].sizemask;
解决键冲突
当两个或两个以上的键分配到哈希数组的同一个索引上时,Redis使用链地址法
解决链冲突
链地址法
哈希表节点都有一个next指针,可以使用next指针构成单向链表。
且dictEntry节点构成的链表没有指向链表末尾的指针,为了节省时间,新的节点一般直接添加到表头位置
rehash(重新散列)
目的
随着哈希表键值对的逐渐增加或减少,为了让哈希表的负载因子维持在一定范围内
步骤
为字典的
ht[1]
哈希表分配空间,这个哈希表的空间大小取决于要执行的操作, 以及ht[0]
当前包含的键值对数量 (也即是ht[0].used
属性的值):如果执行的是扩展操作, 那么
ht[1]
的大小为第一个大于等于ht[0].used * 2
的 (2
的n
次方幂);如果执行的是收缩操作, 那么
ht[1]
的大小为第一个大于等于ht[0].used
的 。
将保存在
ht[0]
中的所有键值对 rehash 到ht[1]
上面: rehash 指的是重新计算键的哈希值和索引值, 然后将键值对放置到ht[1]
哈希表的指定位置上。当
ht[0]
包含的所有键值对都迁移到了ht[1]
之后 (ht[0]
变为空表), 释放ht[0]
, 将ht[1]
设置为ht[0]
, 并在ht[1]
新创建一个空白哈希表, 为下一次 rehash 做准备。
哈希表的收缩与扩展
以下条件满足任意一个时,程序会自动开始对哈希表执行扩展操作:
服务器目前没有在执行 BGSAVE 命令或者 BGREWRITEAOF 命令, 并且哈希表的负载因子大于等于
1
服务器目前正在执行 BGSAVE 命令或者 BGREWRITEAOF 命令, 并且哈希表的负载因子大于等于
5
负载因子计算公式:
# 负载因子 = 哈希表已保存节点数量 / 哈希表大小load_factor = ht[0].used / ht[0].size
当哈希表的负载因子小于 0.1
时, 程序自动开始对哈希表执行收缩操作
渐进式rehash
目的:
假如哈希表中保存了大量的数据,一次性将这些数据进行rehash时会产生庞大的计算量,为了防止rehash对redis的性能产生影响
渐进式rehash实现的详细步骤:
为
ht[1]
分配空间, 让字典同时持有ht[0]
和ht[1]
两个哈希表。在字典中维持一个索引计数器变量
rehashidx
, 并将它的值设置为0
, 表示 rehash 工作正式开始。在 rehash 进行期间, 每次对字典执行添加、删除、查找或者更新操作时, 程序除了执行指定的操作以外, 还会顺带将
ht[0]
哈希表在rehashidx
索引上的所有键值对 rehash 到ht[1]
, 当 rehash 工作完成之后, 程序将rehashidx
属性的值增一。随着字典操作的不断执行, 最终在某个时间点上,
ht[0]
的所有键值对都会被 rehash 至ht[1]
, 这时程序将rehashidx
属性的值设为-1
, 表示 rehash 操作已完成。
渐进式rehash执行期间的哈希表操作
字典的删改查等操作都会在两个哈希表之间共同进行
新增加的键只添加
ht[1]
上
字典API
跳跃表
关键词:
-
前沿资讯!性能测试工具Locust和JMeter比较-及相关书籍下载
ApacheJMeter™和Locust都是是最受欢迎的性能测试工具。JMeter和Locust-简介JMeter是久经考验的性能框架之
来源: 《Redis设计与实现》读书笔记 焦点简讯
2023年团体程序设计天梯赛 题解
环球观天下!并发编程(1)-线程与锁
前沿资讯!性能测试工具Locust和JMeter比较-及相关书籍下载
滚动:新金路(000510.SZ):提请股东大会授权董事局办理以简易程序向特定对象发行股票
英足总杯丨马赫雷斯“戴帽”,曼城挺进决赛|精选
让老外爱上“砍一刀”!拼多多Temu英国站已正式上线 天天亮点
每日播报!圆球停在斜坡顶端 网友称物理学不存在了 体彩中心:可能是天气原因
美国多个州要求召回韩国汽车:缺乏基本的防盗装置 危及公共安全
环球快消息!比亚迪百万豪车!仰望U8开车第一视角曝光:马路都感觉变窄了
蛋蛋面膜真的能去皱纹吗_蛋蛋面膜
「学习笔记」重修 FHQ-treap
Godot 4.0 设置应用程序图标、项目图标
Springboot yml配置参数加密 ,jasypt自定义解密器|当前简讯
国家能源局:截至3月底全国累计发电装机容量约26.2亿千瓦 同比增长9.1%
亚香股份: 2022年年度报告摘要
全球速读:劳斯莱斯不让进展台 小姐姐直接买了仰望U8、仰望U9两款车
【时快讯】广州街头大众CC变道不成 倒车怒撞奔驰E 网友直呼太恶劣
华为宣布开放5G网络能力 自家5.5G比5G快10倍|焦点速读
什么是期货对冲交易 全球独家
每日观点:歌词那些遗憾留在心底_心中的遗憾歌词
人机识别技术再升级,AIGC为验证码带来万亿种新变化_环球关注
从热爱到深耕,全国Top10开源软件出品人手把手教你如何做开源 微头条
当前观察:今日沈阳老凤祥黄金价格查询(2023年4月23日)
全球快播:提车时大风吹倒墙壁新车被砸 男子:4S店只修不换不退
【当前独家】抖音推出种草产品有柿App 由头条搜索升级而来
体彩开奖球停在斜坡不下滚遭质疑是什么情况
观察:厦门国际银行助力企业赴澳发行首笔“深合债”
詹姆斯:我职业生涯中和很多人有过对决 所以我不想谈狄龙 焦点快播
重返韩国!2023《英雄联盟》S13全球总决赛10月开战:赛程抢先看-全球快看
穿一次扔了都不亏!阿里工厂店大促:船袜6毛4一双起
全球报道:傅索安巴甫洛夫 傅索安怎么死的
优化数据呈现方式,分组双轴图是最佳选择|实时焦点
天天百事通!Transformer
无惧百万级并发,GaussDB(for Cassandra)让华为推送服务更快触达
使用手机在网状态查询 API 有效防止虚假注册的设计思路 全球简讯
视焦点讯!CAS的service参数验证
头条焦点:缬怎么读(缬字怎么读“缬”的读音是:[xié]【释义】)
上不上名校的区别,藏在李雪琴陈都灵的采访中,演员层次分出来了
环球简讯:奇瑞艾瑞泽STAR概念实车现身 网友:换个BBA的标 能卖百万
被泰国红牛告了 禁止生产销售!中国红牛回应:系网络水军抹黑-世界热点
【速看料】燕矶长江大桥北锚碇填芯混凝土大方量浇筑打破项目纪录
NGINX 备忘清单_开发速查表分享_时讯
孕产妇营养饮食大全 全球今头条
环球热门:雀巢丝滑拿铁咖啡15瓶到手59.8元:榛果、焦糖等多种口味
外观大变 增插混版!全新广汽本田雅阁将于5月底上市 全球快资讯
SpaceX星舰发射导流槽都没挖!马斯克:大意了 焦点短讯
4种口味任选 超划算:和路雪千层雪冰淇淋3.87元大促 _世界新要闻
有望下跌!国内油价五一节前调整 预计下调0.07元/升-微资讯
最新资讯:泡菜坛口用水密封的目的 泡菜坛口为什么要用水密封呢
华为云GaussDB支撑华为MetaERP系统全面替换
券商业绩大反攻!“券茅”获基金大幅加仓
15平方米公共绿地被居民私自硬化,路长、物业齐出手
具俊晔有孩子吗?具俊晔个人资料简介
超频冲上3.1GHz!索泰RTX 4070天启OC评测:远超公版的2K游戏最香显卡 天天新要闻
天天精选!公司要求开宝马卖车否则开除!员工回应:没人开宝马
黑猫警长一只耳的耳朵是怎么没的?黑猫警长中一只耳的娘舅是谁?
回家的诱惑宝莲身世第几集揭晓?回家的诱惑宝莲最后和谁在一起了?
张萌制片的作品有哪些?男制片人张萌简介
西海情歌的原唱是谁?西海情歌背后真实的故事
outlook怎么设置msn邮箱?outlook怎么撤回邮件?
第四范式联合创始人胡时伟:AIGC可能带来企业生产要素的变化
塞班s60v3还能用微信吗?塞班手机性能排行
三星笔记本r23plus黑屏怎么解决?三星笔记本r23plus配置
地下城与勇士刺客刷图厉害吗?地下城与勇士刺客转职什么好?
常用的 API 大全整理|全球热消息
【全球速看料】【Spring】三级缓存解决循环依赖问题
支付宝安全控件怎么升级?支付宝安全控件有什么用?
花汐与眠王12 看热讯
全球百事通!李楠评MINI冰淇淋事件:宝马公关写道歉信是真的蠢
【新要闻】专注和沉浸 是华为墨水平板赋予信息碎片化时代的“稀缺品”
第28个世界读书日你读书了吗?超8成图书被已婚人群买走:为了下一代-焦点滚动
海南部署开展道路交通安全和运输执法领域突出问题专项整治工作 每日快播
兵马俑景区“五一”门票预售啦
《安富莱嵌入式周报》第310期:集成大语言模型的开源调试器ChatDBG, 多功能开源计算器,M7内核航空航天芯片评估板, Zigbee PRO规范
世界热议:前端跨域解决方案——postMessage
不回皇马!齐达内出山,无视6000万年薪,拒联手C罗,意甲乱了
世界动态:仿真手感 全身可按:允宝充气颈部按摩仪99元新低(335元券)
【播资讯】小米13 Ultra可变光圈能晃动?小米王化科普:正常物理现象
今日上海消费券线上哪些商家可以用(上海消费如何)
微博如何查看自己评论过的动态(微博如何查看自己评论过的动态记录) 每日简讯
每日热门:超快充伤电池吗?实测:240W用了2个月 手机电池健康度依然100%
比亚迪赵长江:很多客户都是抛弃雷克萨斯LM 过来买腾势D9 天天资讯
直降200元!45mm GPS款苹果表8限时好价
朱砂供星月菩提变色8个过程图_朱砂供星月菩提 每日短讯
我国三款商业液体火箭发动机发布!综合性能达国际先进水平
园方回应熊猫阿宝耳朵被咬成V形:繁殖期太激动 没大碍 世界热消息
安卓手机ip地址更换_1024最新手机地址一二
学系统集成项目管理工程师(中项)系列10_立项管理 世界资讯
环球速看:闺女15岁生日送什么礼物,15岁女孩生日,送什么礼物好?
贡萨洛-拉莫斯谈百场里程碑:齐心协力,全力以赴 全球视讯
当前简讯:青龙面板基础知识和使用教程
怎么做动图表情包_怎么做动图-当前热闻
小米13 Ultra供不应求:明天再次开卖 5999元起_每日讯息
成龙新电影《传说》开拍!女主角是古力娜扎
买冰箱空调洗衣机少踩雷!这些选购干货看下
观热点:是不是觉得微博热搜很蠢?他们好像也意识到了 但没办法
车上被砸冰淇淋、遭谩骂!宝马车主无辜受牵连不敢开车出门、要贱卖车:求理性
英雄无悔_关于英雄无悔的简介 世界速递
【世界聚看点】民心佳园新夜市将于4月26日开市丨重庆10区县遭遇暴雨