Redis
2022-11-23 12:15:32 0 举报
redis 学习
作者其他创作
大纲/内容
50
entry2
62
time+∞~0
11
encoding(00001011)
refcount
7
free
redisObject
100
....
RedisObject
*key(8B)
len
embstr 编码方式
w(10)
RedisObject的作用Redis 的数据类型有很多,不同数据类型都有些相同的元数据要记录(比如最后一次访问的时间、被引用的次数等),所以,Redis 用RedisObject 结构体来统一记录这些元数据,同时指向实际数据。
entryN
used:2
3
zltail
size3
dictEntry
.......
dup
15
*value(8B)
1
next
2
typedef struct listNode { //前置节点 struct listNode *prev; //后置节点 struct listNode *next; //节点的值 void *value;} listNode;
content
typedef struct dictEntry { //键值对中的键 void *key; //键值对中的值 union { void *val; uint64_t u64; int64_t s64; double d; } v; //指向下一个哈希表节点,形成链表 struct dictEntry *next;} dictEntry;
查找33 需要3次
dictEntry[4]
跳表
27
4
typedef struct dictht { //哈希表数组 dictEntry **table; //哈希表大小 unsigned long size; //哈希表大小掩码,用于计算索引值 unsigned long sizemask; //该哈希表已有的节点数量 unsigned long used;} dictht;
w(5)
RedsObject(Zset)
0
encoding
zlbytes:列表长度zltail:列表尾的偏移量zllen:列表中的 entry 个数zlend:列表结束
双向链表
原数据(8B)
key
14
notused
*next(8B)
redisClient
RedsObject(Hash)
redisObject对SDS 的内存布局的优化当保存的是 Long 类型整数时,RedisObject 中的指针就直接赋值为整数数据了,这样就不用额外的指针再指向整数了,节省了指针的空间开销。当保存的是字符串数据,并且字符串小于等于 44 字节时,RedisObject 中的元数据、指针和 SDS 是一块连续的内存区域,这样就可以避免内存碎片。这种布局方式也被称为 embstr 编码方式。当字符串大于 44 字节时,SDS 的数据量就开始变多了,Redis 就不再把 SDS 和 RedisObject 布局在一起了,而是会给 SDS 分配独立的空间,并用指针指向 SDS 结构。这种布局方式被称为 raw 编码模式。
简单动态字符串
8
expires
压缩列表
value
alloc(4B)
prev_len
12
dict
5
6
entry1
prev
9
ptr(8B)
listNode模型
整数数组
SDS
ptr(8B):直接将数据存在此处
Redis 在 listNode 结构体基础上又封装了 list 这个数据结构,这样操作起来会更方便链表每个节点之间的内存都是不连续的,意味着无法很好利用 CPU 缓存。能很好利用 CPU 缓存的数据结构就是数组,因为数组的内存是连续的,这样就可以充分利用 CPU 缓存来加速访问。
RedsObject(List)
10
match
dictht
默认指向0,如果执行select操作则则可更改
db
dicht
156
w(2)
ht[1]
RedisObject的模型
zllen
.....
33
RedisServer
buf(\"redis\\0\")
typedef struct redisObject { // 类型 unsigned type:4; // 对齐位 unsigned notused:2; // 编码方式 unsigned encoding:4; // LRU 时间(相对于 server.lruclock) unsigned lru:22; // 引用计数 int refcount; // 指向对象的值 void *ptr;}
type
size:4
entry模型
len(4B)
#define REDIS_STRING 0 // 字符串#define REDIS_LIST 1 // 列表#define REDIS_SET 2 // 集合#define REDIS_ZSET 3 // 有序集#define REDIS_HASH 4 // 哈希表
table
*table
len(11)
w(7)
//对象编码#define REDIS_ENCODING_RAW 0 // 编码为字符串#define REDIS_ENCODING_INT 1 // 编码为整数#define REDIS_ENCODING_HT 2 // 编码为哈希表#define REDIS_ENCODING_ZIPMAP 3 // 编码为 zipmap#define REDIS_ENCODING_LINKEDLIST 4 // 编码为双端链表#define REDIS_ENCODING_ZIPLIST 5 // 编码为压缩列表#define REDIS_ENCODING_INTSET 6 // 编码为整数集合#define REDIS_ENCODING_SKIPLIST 7 // 编码为跳跃表
tail
prev_len:表示前一个 entry 的长度。prev_len 有两种取值情况:1 字节或 5 字节。取值 1 字节时,表示上一个 entry 的长度小于 254 字节。虽然 1 字节的值能表示的数值范围是 0 到 255,但是压缩列表中 zlend 的取值默认是 255,因此,就默认用 255 表示整个压缩列表的结束,其他表示长度的地方就不能再用 255 这个值了。所以,当上一个 entry 长度小于 254 字节时,prev_len 取值为 1 字节,否则,就取值为 5 字节。len:表示自身长度,4 字节;encoding:表示编码方式,1 字节;content:保存实际数据。
RedsObject(Set)
*ptr
raw 编码方式
redisDB
w(3)
20
head
rehashidx
SDS(简单动态字符串)
content(hello world)
zlend
查找33 需要4次
ht
nil
Value
HASH
dictEntry[3]
int 编码方式
w(9)
lru
length
zlbytes
13
ht[0]
entry demo
哈希表
encoidng
buf:字节数组,保存实际数据。为了表示字节数组的结束,Redis 会自动在数组最后加一个“\\0”,这就会额外占用 1 个字节的开销。len:占 4 个字节,表示 buf 的已用长度。alloc:也占个 4 字节,表示 buf 的实际分配长度,一般大于 len。
RedsObject(String)
entry3
used:0
0 条评论
下一页