Redis< String > Redis String
Redis String 类型,存储字节,包括文本,序列化对象和二进制数组,因此 String是Redis最基本的数据结构 。通常用于缓存,而且Redis支持其他功能,允许实现计数器并执行按位运算.
由于Redis中key是一个字符串,因此Redis使用String数据结构作为key的值.
在默认情况下,Stirng最大为512MB,可以通过配置项proto-max-bulk-len
进行修改.
String 适用场景
使用场景:一般用来存放字节数据、文本数据、序列化后的对象数据.
- 缓存场景:Value存Json字符串等信息.
- 计数场景:因为Redis处理命令是单线程,所以执行命令的过程是原子的,因此String数据结构适合计数场景.
String 命令
常用命令:
- 创建 -->
set
,setnx
,getset
SET key value
# 设置一个key值为特定的value
set命令扩展参数: EX(键过期时间秒)、PX(键过期时间毫秒)、NX(只有键不存在时才对键进行操作,基本替代下面的SETNX操作)、XX(键存在时才对键进行操作)
SETNX key value
# 用于在指定的key不存在时,为key设置指定的值,对于实现锁很有用GETSET key value
# 设置一个key的值,并返回原来的值
- 查询 -->
get
,mget
Get key
# 查询某个key,存在就返回对应的value,不存在返回nilMget key [key ...]
# 一次查询多个key,如果某个key不存在,对应位置返回nil
- 更新 -->
set
- 见上面的set命令
- 删除 -->
del
DEL key [key ...]
# 删除对象,返回值为删除成功了几行
其他命令:incr
, incrby
, incrbyfloat
INCR key [increment]
# 以原子方式将给定键中存储的计数器加 1INCRBY key increment
# 以原子方式将给定键中存储的计数器加上指定的增量值INCRBYFLOAT key increment
# 以原子方式将给定键中存储的计数器加上指定的浮点数增量值
String 编码(底层实现)
Redis String类型,底层实现是使用C语言的SDS
字符串类型,sds类型是Redis自己实现的一种动态字符串类型,它比C语言的String
类型多了一个指针,指向字符串的结尾,方便在字符串末尾追加数据。
- String的三种编码方式:
INT
: 存放整形,可以用long表示的整数以该编码存储;EMBSTR
: 如果字符串 <= 阈值字节(redis.version > 3.2 ? 44 : 39),使用EMBSTR编码RAW
: 字符串大于 > 阈值字节(redis.version > 3.2 ? 44 : 39),使用RAW编码
点击查看EMBSTR的阈值为什么是44?
阈值字节: 在源码中使用OBJ_ENCODING_EMBSTR_SIZE_LIMIT宏定义,默认为44字节,在Redis 3.2版本中,该阈值是39字节.
- Redis默认使用jemalloc作为内存分配器
- jemalloc是以64字节作为内存单元做内存分配,如果超出了64个字节就超过了一个内存单元. 在内存分配时,RedisObject会尽量在一个内存单元,是为了减少内存寻址,又不会消耗分配过多没用到的内存,
- 围绕64字节的关键分界分析版本变化,Redis的字符串对象是由一个
RedisObject
+sdshdr
两部分组成,- RedisObject大小为
4+4+24+32+64 = 128bits = 16bytes
,其中的ptr是64,是为了方便各种编译器和目标平台上使用 - sdshdr8占用内存大小: 1byte + 1byte + 1byte + 内联数组的大小,由于内联数组中还有一个'\0'占位一个字符,所以能用的大小为64-16(redisObject)-3(sdshdr非内容属性)-1('\0')=44
- RedisObject大小为
RedisObject Struct:
c
#define LRU_BITS 24
typedef struct reidsObject {
unsigned type:4; // 4 bit
unsigned encoding:4; // 4 bit
unsigned lru:LRU_BITS; // 24 bit
int refcount; // 32 bit
void *ptr; // 64 bit
} robj; // 128 bit == 16 bytes
sdshdr Struct:
c
struct __attribute__((__packed__)) sdshdr8 {
uint8_t len; // 1 byte
uint8_t alloc; // 1 byte
unsigned char flags; // 1 byte
char buf[]; // '\0' 占位符 1 byte
}
EMBSTR
和RAW
是由redisObject和SDS
两个结构组成,两者差异在于EMBSTR
编码下redisObject和SDS是连续的内存,RAW编码下redisObject和SDS的内存是分开的.
EMBSTR的优缺点:
- 优点:一次性分配内存,redisObject和SDS两个结构一次性分配内存
- 缺点:重新分配空间时,整体需要重新再分配
- EMBSTR设计为只读,任何写操作之后EMBSTR都会变成RAW
编码转化的可能:
- INT -> RAW: 当内存不再是整形,或者大小超过了long
- EMBSTR -> RAW: 任何写操作之后EMBSTR都会变成RAW
SDS解释
🔗 查看SDS