读<<Redis设计与实现>>与redis(5.0)源码__对象
redisObject
1 |
typedef struct redisObject { |
-
type类型
1
2
3
4
5
6
7 -
encoding编码
1
2
3
4
5
6
7
8
9
10
11
t_string
- 有三种编码方式,OBJ_ENCODING_INT,OBJ_ENCODING_EMBSTR,OBJ_ENCODING_RAW
- OBJ_ENCODING_EMBSTR_SIZE_LIMIT = 44,也就是小于等于44子长用embstr编码,大于就用raw.因为redisObject大小 = (4+4+24)/8+4+8 = 16,sdshdr8除去buf外的大小是3(len,alloc,flag),预留1byte的’\0’,供20byte.redis的内存分配方法按2^n分配,所以最接近的是64,剩下44byte.
- tryObjectEncoding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/* Try to encode a string object in order to save space */
robj *tryObjectEncoding(robj *o) {
long value;
sds s = o->ptr;
size_t len;
/* Make sure this is a string object, the only type we encode
* in this function. Other types use encoded memory efficient
* representations but are handled by the commands implementing
* the type. */
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
/* We try some specialized encoding only for objects that are
* RAW or EMBSTR encoded, in other words objects that are still
* in represented by an actually array of chars. */
if (!sdsEncodedObject(o)) return o;
/* It's not safe to encode shared objects: shared objects can be shared
* everywhere in the "object space" of Redis and may end in places where
* they are not handled. We handle them only as values in the keyspace. */
if (o->refcount > 1) return o;
/* Check if we can represent this string as a long integer.
* Note that we are sure that a string larger than 20 chars is not
* representable as a 32 nor 64 bit integer. */
len = sdslen(s);
// 20减去4个长度剩下16,2^64~=1.84E19(所以超过20位,减去符号19位,超过了int64表示的极限)
if (len <= 20 && string2l(s,len,&value)) { // 是整数
/* This object is encodable as a long. Try to use a shared object.
* Note that we avoid using shared integers when maxmemory is used
* because every object needs to have a private LRU field for the LRU
* algorithm to work well. */
// 如果设置了最大使用内存,说明要进行回收,不能有共享变量(要LRU)
if ((server.maxmemory == 0 ||
!(server.maxmemory_policy & MAXMEMORY_FLAG_NO_SHARED_INTEGERS)) &&
value >= 0 &&
value < OBJ_SHARED_INTEGERS)
{
decrRefCount(o);
incrRefCount(shared.integers[value]);
return shared.integers[value];
} else {
if (o->encoding == OBJ_ENCODING_RAW) sdsfree(o->ptr);
o->encoding = OBJ_ENCODING_INT;
o->ptr = (void*) value;
return o;
}
}
/* If the string is small and is still RAW encoded,
* try the EMBSTR encoding which is more efficient.
* In this representation the object and the SDS string are allocated
* in the same chunk of memory to save space and cache misses. */
// 如果小于等于44,改用EMBSTR
// 说明默认是RAW编码
if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT) {
robj *emb;
if (o->encoding == OBJ_ENCODING_EMBSTR) return o;
emb = createEmbeddedStringObject(s,sdslen(s));
decrRefCount(o);
return emb;
}
/* We can't encode the object...
*
* Do the last try, and at least optimize the SDS string inside
* the string object to require little space, in case there
* is more than 10% of free space at the end of the SDS string.
*
* We do that only for relatively large strings as this branch
* is only entered if the length of the string is greater than
* OBJ_ENCODING_EMBSTR_SIZE_LIMIT. */
trimStringObjectIfNeeded(o);
/* Return the original object. */
return o;
}
t_list
- 编码方式有OBJ_ENCODING_QUICKLIST(OBJ_ENCODING_LINKEDLIST被弃用)(,OBJ_ENCODING_ZIPLIST在list里没用了)
- quicklist
- 将linkedlist和ziplist混合起来使用,每个节点是一个ziplist
- list-max-ziplist-size设置ziplist的大小,正数表示长度,负数表示 -n = 2^(n+1)kb
t_hash
- 编码方式有OBJ_ENCODING_ZIPLIST,OBJ_ENCODING_HT
- 如果长度大于server.hash_max_ziplist_entries,转换成OBJ_ENCODING_HT
- 如果键值的长度大于 server.hash_max_ziplist_value,转换成OBJ_ENCODING_HT
t_set
- 编码方式有OBJ_ENCODING_HT,OBJ_ENCODING_INTSET
- 如果长度大于server.set_max_intset_entries,或者有非整数,转换成OBJ_ENCODING_HT
t_zset
- 编码方式有OBJ_ENCODING_ZIPLIST,OBJ_ENCODING_SKIPLIST
- 如果长度大于server.zset_max_ziplist_entries,或者有非整数,转换成OBJ_ENCODING_SKIPLIST
- 如果值的长度大于 server.zset_max_ziplist_value,转换成OBJ_ENCODING_SKIPLIST