Redis:string类型
- string命令
- 设置与读取
- SET
- GET
- MSET
- MGET
- 数字操作
- INCR
- INCRBY
- DECR
- DECRBY
- INCRBYFLOAT
- 字符串操作
- APPEND
- STRLEN
- GETRANGE
- SETRANGE
- 内部编码
- int
- embstr
- raw
在Redis
中,字符串string
存储的是二进制,以byte
为单位,输入的二进制是什么,那么存储的就是什么,string
不进行编码的转化。
因此string
类型可以存储非常多种类的数据,比如ASCII
编码字符串,UTF-8
编码字符串,int
整型,甚至可以存储图片,视频音频等,因为这些都是二进制,怎么存进去的,最后就怎么解析。
当然,一般不会用string
存储图片,视频音频,因为它们太大了,内存没那么多空间,只是理论上可行。
string命令
设置与读取
SET
- 设置一个
key
set key value [EX seconds | PX milliseconds] [NX | XX]
由于set
默认情况下就是设置一个string
,所以没有什么其它的特殊语法,此处介绍两个选项。
EX seconds
:以秒为单位,设置超时时间PX milliseconds
:以毫秒为单位,设置超时时间NX
:如果key
不存在才设置,如果存在返回nil
XX
:如果key
存在就更新,如果不存在返回nil
注意:通过XX
更新后,原先的过期时间会失效,数据类型也有可能变化
示例:
该指令设置了一个字符串key1
,内容为12345
,过期时间为10 s
,nx
表示只有不存在才设置。
示例:
和刚才一样设置一个超时时间10 s
的字符串,随后立刻通过xx
选项进行更新操作。更新后发现,ttl
的返回值变成了-1
,这说明原先ex
设置的过期时间被覆盖了。
GET
- 获取
key
对应的value
get key
和set
一样,get
的默认数据类型就是string
,如果value
类型不是string
,会发生报错。
MSET
- 一次设置多个
key
mset key value [key value ...]
由于Redis
基于网络通信,所以多条指令压缩为一条指令就是把多个网络请求压缩为一个,对效率提升非常明显。所以Redis
提供了这样的一次设置多组键值对的指令。
MGET
- 一次获取多个
key
的value
mget key [key ...]
示例:
数字操作
由于string
内部还可以存储数字,所以Redis
还提供了数字操作的命令。
INCR
- 指定整数
+1
incr key
返回值是字符串+1
后的结果。
示例:
如图,设置了一个数字后,通过incr
对其自增,返回了124
,并且get num1
的值也自增了。
当设置的数字值过大,此时就不会被解析为数组,而是解析为字符串。此时incr
执行失败,检测到num2
类型为embstr
。string
可以存储的最大整型为64位有符号整型
,相当于C/C++
中的long long
。
另外的,incr
可以操作一个空值,并且将其视为数字0
。此处通过get
检测num3
不存在,但是incr num3
成功执行,结果为1
。
INCRBY
- 指定整数,增加指定的值
incrby key increment
key
对应的value
的值就会增加increment
,其余特性和incr
相同。
示例:
注意:incrby
可以增加一个负数,也就是做减法。但是不能操作浮点数,只能操作整型。
DECR
- 指定整数
-1
decr key
返回值是字符串-1
后的结果。
DECRBY
- 指定整数,减少指定的值
decrby key decrement
key
对应的value
的值就会减少decrement
,其余特性和decr
相同。
同样的,decrby
也可以操作负数,此时相当于增加decrement
的绝对值。
INCRBYFLOAT
- 指定浮点数/整数,增加指定的值
incrbyfloat key increment
同样的,返回key
的value
自增后的值。
示例:
与整型不同,Redis
没有提供DECRBYFLOAT
指令,也就是说浮点数想要进行减法,只能让increment
为负数。
字符串操作
回到string
的本职工作,自然是要存储字符串,字符串也要提供相关的操作。
APPEND
- 将
value
追加字符串的尾部
append key value
返回追加完成后,字符串的总长度。
如图完成了一个字符串的追加。
同样的,如果原先key
不存在,则视为一个空串,直接追加。
STRLEN
- 获取字符串的长度
strlen key
返回字符串的长度,以字节为单位。
如果遇到中文:
此时根据UTF-8
编码,一个中文占3 byte
,所以两个中文的长度是6
。如果再输出这个中文字符串,会得到一个乱码。此处\x
是一个转义字符,表示一个十六进制数字。也就是说\xe4
整体是一个十六进制的数字,占一个字节。
其实这个十六进制数字,就是汉字的编码,比如\xe4 \xdb \xa0
就是汉字"你"
。如果想要让Redis
支持输出中文,在启动时要加入--raw
选项:
这样就可以正常输出中文了,但是要注意,如果key
不存在,原本是输出nil
,但是会被转化为一个空行。
GETRANGE
- 返回字符串指定范围的字串
getrange key start end
获取的字串是下标范围[start, end]
的闭区间,下标从0
开始。而且支持使用负数,最后一个字符串的负数编码为-1
。
示例:
第一次截取,区间为[0, 5]
,由于是闭区间,所以有6
个字符。
第二次截取,区间为[0, -1]
,-1
就是最后一个字符,又是闭区间,所以输出整个字符串。
如果存储汉字,此时依然以字节解析,而不是以字符为单位。
如果开启了--raw
选项:
此时汉字"好"
截取了一半,但是不输出,只有"你"
被完整拆分下来,才能解析。
SETRANGE
- 修改指定范围内的字符串
setrange key offset value
从下标offset
位置开始覆盖,字符串替换为value
,返回替换后的字符串长度。
示例:
此处从下标5
,也就是字符w
开始覆盖,往后三个字符替换为cpp
,而ld
不变。
如果字符串覆盖后超出原先的长度,此时字符串就会变长。
对于不存在的key
:
如果在空的key
后面修改字符串,此时offset
之前的所有字节自动初始化为\x00
,offset
之后的内容正常覆盖。
总结:
命令 | 执行效果 |
---|---|
set key value[key value...] | 设置key 的值为value |
get key | 获取key 的值 |
del key[key...] | 删除指定的key |
mset key value[key value ...] | 批量设置指定的key 和value |
mget key[key...] | 批量获取key 的值 |
incr key | 指定的整数 的值+1 |
decr key | 指定的整数 的值-1 |
incrby key n | 指定的整数 的值+n |
decrby key n | 指定的整数 的值-n |
incrbyfloat key n | 指定的整数/浮点数 的值+n |
append key value | 指定的字符串 追加value |
strlen key | 获取指定字符串 的长度 |
setrange key offset value | 覆盖指定字符串 从offset 开始的部分值 |
getrange key start end | 获取指定字符串 从start 到end 的部分值 |
内部编码
在 Redis
中,string
数据类型的底层实现有三种编码方式:int
、embstr
和 raw
。每种编码方式有其特定的使用场景和实现细节,以优化内存使用和性能表现。
int
当一个字符串的值可以被解析为整数(有符号的 64 位整数范围内)时,
Redis
会将其存储为整数
int
编码使用 8 byte
来存储整数值。这种方式的优势在于节省存储空间并提高处理速度,因为整数操作比字符串操作更高效。
embstr
用于存储长度小于或等于
39 byte
的字符串。
embstr
编码是为了优化小字符串的内存分配和管理而设计的。embstr
的实现将字符串对象的结构和实际字符串数据放在一起,这样在创建时只需要一次内存分配。其包含一个 SDS
(Simple Dynamic String
)结构,用于管理字符串的长度等信息。
这种方式减少了内存碎片,提高了缓存的局部性,并使得创建和销毁字符串对象的速度更快。
raw
用于存储长度大于
39 byte
的字符串。
raw
编码是传统方式,分开存储字符串对象和字符串数据。与 embstr
不同,raw
编码需要两次内存分配:一次用于存储字符串对象的基本信息,比如长度,另一次用于实际的字符串数据。
这种方式允许更灵活的字符串管理,适合处理较大字符串的场景。在需要对字符串进行修改时,raw
编码也能更好地管理内存。