Redis知识梳理(2)当我们谈到string的时候,我们在谈什么?

数据结构

Redis中的string数据类型的数据结构类似Java中的ArrayList,是一个字符数组。

扩容机制

当字符串大小 > 1MB的时候,每次扩容都会扩容一倍。当字符串大小 < 1MB的时候,每次扩容就扩容1MB。Redis约定Redis中的String大小最大为512MB

计数器

如果Redis中的String存储的值的类型是num,那么可以使其自增。但是自增的最大值为Long.MAX_VALUE

可修改性

Redis你给的字符串是可修改的,换而言之,他不是每次赋值或者修改都是重新建一个String对象在内容中。

源码分析

struct SDS<T> {
    T capacity;					// 数组的容量
    T len;						// 数组的长度
    byte flags;					// 数组的特殊标志位
    byte[] content;				// 数组的内容
}

创建字符串的时候,初始化的数组容量和数组的长度是一样的长的。

存储方式

redis中String又两种存储方式:

  1. embstr
  2. raw

(如果希望查看redis中的String使用了那种存储方式可以通过debug object keyName的方式来进行查询)

redis1.cluster.oilchem.local:0>set test77 01234567890123456789012345678901234567891234
"OK"

redis1.cluster.oilchem.local:0>debug object test77
"Value at:0x7f2dadae5240 refcount:1 encoding:embstr serializedlength:22 lru:13329039 lru_seconds_idle:1"



redis1.cluster.oilchem.local:0>set test77 012345678901234567890123456789012345678912345
"OK"

redis1.cluster.oilchem.local:0>debug object test77
"Value at:0x7f2d98961060 refcount:1 encoding:raw serializedlength:23 lru:13328992 lru_seconds_idle:2"

根据上面的例子可以看出,当字符串的内容长度超过44之后,string 的存储方式会从embstr转换为raw。但是为什么分界值是44呢?

为了解释这种现象,需要先了解一下Redis对象的定义

struct RedisObject {
	int4 type;			// 4bit 对象的类型
    int4 encoding;		// 4bit 对象的存储形式
    int24 lru;			// 24bit LRU信息
    int32 refcount;		// 4bytes 引用计数器,其为0时,对象被回收
    void *prt;			// 8bytes 64-system 指针,指向对象内容存储位置
} robj;					// 其总大小是为16 bytes

接着你来看一下SDS结构体的大小,存储字符串比较小的时候,SDS对象头结构大小为3字节

struct SDS{
    int8 capacity;		// 8bit	数组的容量
    int8 len;			// 8bit 数组长度
    int8 flags;			// 8bit 特殊标志位
    byte[] content;
}						// 其总大小为 3byte

这意味着分配一个字符串的最小空间占用为 16bytes + 3bytes = 19bytes

Redis认为一个字符串总体超出了64字节为一个大字符串,不适合使用embstr,那当内存分配了64字节空间的时候,字符串的最大长度为:

	64bytes - 19bytes = 45bytes;

但SDS结构体中content中的字符串是以字节null结尾的字符串,所以embstr的最大能容纳的字符串长度为

	64bytes - 19bytes - 1bytes = 44bytes;

embstr和raw在内存上的区别

embstr,它将RedisObject对象头结构和SDS对象连续存储在一起的,使用malloc方法一次分配:

raw的存储形式不一样,它想需要使用两次malloc方法,两个对象头在内存地址上一般是不连续:

posted @ 2020-05-25 14:45  joimages  阅读(197)  评论(0编辑  收藏  举报