本文已参与[新人创作礼]活动,一起开启掘金创作之路。
Redis基础篇--string
string
内部实现: 动态字符串,类似于JAVA的ArrayList。采取预分配的方式,其分配的实际空间 capacity 一般高于实际长度len。当字符串长度小于1M时,扩容都是加倍;当超过1M时,一次只会多扩1M。注意:其最大长度为512MB.
常见命令:
键值对
set key value #设置key的值为value
get key #获取key的值
exists key #key是否存在
del key #删除key
批处理
mget key1 key2 #批量获取key
mset key1 value1 key2 value2 #批量设置key和value
过期和set命令扩展
expire key time #time 秒后过期
setex name 5 whoops #5s后过期,等价于set+expire
setnx name whoops # 如果name不存在就执行set创建
计数 如果一个value是一个整数,还可以对它进行自增操作。自增是有范围的,它的范围在signed long的最大值和最小值之间,超过了这个范围,redis会报错
set age 30
incr age #执行自增指令
内部实现
struct SDS<T>{
T capacity; /* 数组容量 */
T len; /* 数组长度 */
byte flags; /* 特殊标志位,不用理踩 */
byte[] content; /* 数组内容 */
}
Redis对内存做了极致优化,不同长度的字符串使用不同的结构体来表示.其有两种存储形式,长度特别短的时候使用embstr形式,而当长度超过44字节时,使用raw形式存储
借助 debug object key可以获取key的存储信息
redis对象头结构如下:
struct RedisObject {
int4 type; /* 4bits */
int4 encoding; /* 4bits */
int24 lru; /* 24bits */
int32 refcount; /* 4bytes */
void *ptr; /* 8bytes,64-bit system */
} robj;
这样一个RedisObject对象头结构需要16字节的存储空间,再看SDS结构体大小
struct SDS<T>{
int8 capacity; /* 1byte */
int8 len; /* 1byte */
int8 flags; /* 1byte */
byte[] content; /* 内联数组,长度为capacity */
}
SDS对象头结构的大小至少是3,因此意味着分配一个字符串的最小空间占用为19字节(即16+3)
embstr 将RedisObject对象头结构和SDS对象连续存储一起,使用malloc方法一次分配,而raw存储形式不一样,它需要使用两次malloc方法,两个对象头在内存地址上一般是不连续的,而内存分配器jemalloc,tcmalloc等分配内存大小的单位都是2/4/8/16/32/64字节,为了容纳一个完整的embstr对象,jemalloc最少会分配32字节。
当分配了64字节时,字符串的最大长度为44字节。 计算 66-19-1(字符串以NULL结尾)=44字节