目录
简单动态字符串SDS
简单动态字符串的buf底层是通过数据来装的,SDS的API都是二进制安全的,程序不会对其中的数据做任何限制、过滤或者假设(写入和读出都是一样的)。所以buf部分也叫字节数据的原因
预内存分配和惰性空间释放
背景:C的字符串进行扩展和删除的时候,都要进行重新进行内存分配,次数过多会影响性能。SDS结构:
buf:redies不是用数组来保存字符,而是用它来保存二进制数据。实现了1、二进制安全来存放数据,不会对数据进行任何的过滤和修改。2、可以适应各种应用场景(C字符串选用一种编码来存放字符,末位是'\0'代表空位,中间不能存放空格)
注意:redis依然保留在最后以"\0"结尾,目的是为了能重用一部分<string.h>库定义的函数。比如 strcasecmp函数,用于对比俩个字符串。减少了重复的代码。
记录自身长度的好处
1、获取length的长度复杂度是O(1)
2、可以自动进行内存的一个扩充,方便修改字符串,防止内存泄露。
空间预分配方式和惰性空间释放为了解决
对于字符串的拼接操作(append)和截断操作(trim)前者会造成内存溢出(占用了其他的内存空间),后者会造成内存泄露(无用的内存没有释放)
空间预分配方式
惰性空间释放
注意:同时redies的api(sdsclear)也可以在有需要的时候彻底的释放SDS的未使用空间。
总结
链表
结构
应用
字典
结构
dict表示一个字典,ht包含俩个元素的数组,ht[1]在rehash ht[0]的时候起作用,rehashidx用来标记是否正在进行rehash。type和privdata介绍:
dictht封装了hash表,其中size和used使得查询hash表长度的时候复杂度是O(1),其中hash叫:dictEntry*[4],其中每个项是hash表节点:dictEntry,是一包含了key和value的struct,它的末尾总是指向null。
如何放置
解决hash冲突
方法:redis的hash表使用链地址法(separate chaining)来解决键冲突。因为dictEntry节点组成的链表没有指向链表表尾的指针,为了速度,程序总是将新节点添加到链表的表头位置。
渐进式rehash
执行时机
步骤
图解
跳跃表
背景
结构
途中虚线是遍历跳跃表的路径
整数
介绍
结构
图解
整数升级
步骤
现在需要需要增加一个int32的数字65535
step1:
step2:
新分配的空间大小=4*32-16*3=80
step3:
step4:
新增的元素不一定是放在末尾,如果都小于现有元素,就会被放置在开头。
升级利弊
好处:节约内存(只在需要存放更大的数字才会进行升级),增加灵活性。
缺点:升级后的数组不能降级。