1. 编码
字符串对象的编码可以是int、raw、embstr三种。
int: 对象保存的是整数值,并且可以使用long类型进行表示,那么ptr中存储的就是这个long的地址,并将编码设置为int,[0, 10000)范围的可以使用共享整数。
raw: 对象保存的是字符串,且长度大于44字节,使用raw编码。
embstr: 对象保存的是字符串,若长度小等于44字节,则使用embstr类型编码,embstr是一种sds字符串,使用固定的SDS_TYPE_8进行存储,只进行一次内存分配,分配redis对象内存空间和sds对象内存空间,它们是连续存储的。
Redis中浮点类型作为字符串值来保存。
2. 命令
命令 | 作用 |
---|---|
SET | 设置指定 key 的值 NX:仅key不存在 XX: 仅key存在 EX: 过期秒数 PX: 过期毫秒数 |
GET | 获取指定 key 的值。 |
SETNX | 只有在 key 不存在时设置 key 的值 |
SETEX | 设置key的值,并给定过期时间seconds |
GETSET | 将给定 key 的值设为 value ,并返回 key 的旧值(old value) |
SETRANGE | 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始 |
GETRANGE | 获取key 中字符串值的[start,end]的值 |
MSET | 同时设置一个或多个 key-value 对 |
HGET | 获取所有(一个或多个)给定 key 的值 |
INCR | 将 key 中储存的数字值增一 |
INCRBY | 将 key 所储存的值加上给定的增量值(increment) |
INCRBYFLOAT | 将 key 所储存的值加上给定的浮点增量值(increment) |
DECR | 将 key 中储存的数字值增一 |
DECRBY | key 所储存的值减去给定的减量值(decrement) |
APPEND | 追加value到key所存储字符串的后面,key不存在则添加 |
STRLEN | 获取key所存储字符串的长度 |
- 相同命令不同的编码区分
命令 | int 编码 | embstr编码 | raw编码 |
---|---|---|---|
SET | 底层使用整数值进行存储,[0,1000)使用共享整数存储 | 使用简单动态字符串存储,SDS_TYPE_8 | 使用简单动态字符串存储,长度超过44字节时使用 |
GET | 拷贝底层存储的整数值,将其转换为字符串后返回给客户端 | 直接返回字符串给客户端 | 直接返回字符串给客户端 |
INCR | 对整数值进行加法,计算结果仍能用在整数值范围,则直接存储,否则转换编码方式为RAW | 取出字符串并尝试转换成long long类型,失败则告诉客户端,成功则创建新的字符串保存 | 取出字符串并尝试转换成long long类型,失败则告诉客户端,成功则创建新的字符串保存 |
INCRBYFLOAT | 取出整数转换成long double,对齐进行浮点操作后,创建新的字符串对象保存起来 | 取出整数转换成long double,对齐进行浮点操作后,创建新的字符串对象保存起来 | 取出整数转换成long double,对齐进行浮点操作后,创建新的字符串对象保存起来 |
APPEND | 调用 sdscatlen 函数,将字符串添加到末尾 | 调用 sdscatlen 函数,将字符串添加到末尾 | 调用 sdscatlen 函数,将字符串添加到末尾 |
STRLEN | 直接获取字符串的长度 | 直接获取字符串的长度 | 直接获取字符串的长度 |
若对象进行了共享,那么修改对象的操作则会拷贝一个新的对象,而不是用原来的共享对象
3. 源码剖析
- 创建字符串对象
1 | /** |
- 通过long long类型创建字符串对象
1 | robj *createStringObjectFromLongLong(long long value) { |
- 尝试对字符串对象进行编码优化
1 | robj *tryObjectEncoding(robj *o) { |
- SET命令底层实现
1 | void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire, int unit, robj *ok_reply, robj *abort_reply) { |
- INCR和DECR底层实现
1 | void incrDecrCommand(client *c, long long incr) { |