String
redis是基于c语言开发的,但是它并没有沿用c语言的数据结构,而是使用了SDS简单动态字符串(simple dynamic string)这种数据结构
redis 3.2 以前
/* * 保存字符串对象的结构 */ struct sdshdr { // buf 中已占用空间的长度 int len; // buf 中剩余可用空间的长度 int free; // 数据空间 char buf[]; };
在c中对字符串的定义是这样的
char data[]="test\0"
但是在redis中需要适配不通的语言java ,go.php等
在redis中的数据结构是这样的
sds:
free=0
len=4
char data[]="test"
redis中空间换时间
如果把test修改为 test123 redis会自动扩容
(原lengs 4+需要扩容的lengs 2)x 2=12
即变为
sds:
free=12
len=6
char data[]="test123"
用掉2个lengs变为
sds:
free=10
len=6
char data[]="test123"
这种方法可以有效地减少内粗的分配
兼容c语言的函数库
二进制安全
redis是k-v的数据结构,底层使用数据和链表进行数据划分,类似于java中hashmap的实现
默认创建arr[4]的数组来存放数据
假如有三组数据
(k1,v1) (k2,v2) (k3,v3)
通过hash算法运算计算出数组下标位置
假设数据
hash(k1)% 4 = 0
hash(k2)%4 =1
hash(k3)%4 = 1
arr[0]->(k1,v1,next->nul1) 链表指向null
产生hash冲突
arr[1]->(k3,v3,next ->k2 )(k2,v2,next ->null) 链表指向next节点.
redisDB
redis默认15个db 数据库
底层c语言数据结构
dict是redis中的hashtable
dict中的数据结构
dictType 类型
hashFunction指定hash的key名称
keyCompare指定hash比较 有可能产生hash冲突
dictht
如果size=used 会进行数组扩容 如arr[4] 变为 arr[8]
其实就是hashtable的数据结构 有两个[0][1]
arr现长度为4 如果扩容到很大的一个长度 数组结构是需要重新创建一个新的数组 再把原先的数据复制进去,这个过程如果跨度很大的话是很消耗性能的
所以redis定义了一个渐进式的rehash
每次访问的时候搬过来一点数据
如果一直没访问的话,redis内部也会有任务去执行 一点点的把数据全部搬过来
在访问的时候如果数据还没完全搬完 会先去[0]中查找 再去[1]中查找
size hashtable的容量
sizemask 实际长度
dictEntry table
key就是sds对象
next 是链表结构的指针
val 是指向的类型 如String list hash set
类型封装成了object
type 约束redis命令 如set get 不能超出规则范围
refcount redis中没有垃圾收集器 需要知道对象的有效个数
ptr 对象类型的真正指向
指向图