String 字符串
字符串类型是 Redis 最基础的数据类型,关于字符串需要特别注意:
- 首先 Redis 中所有的键的类型都是字符串类型,而且其他几种数据结构也都是在字符串的基础上构建的。
- 字符串类型的值实际可以是字符串,包含一般格式的字符串或者类似 JSON、XML 格式的字符串;数字,可以是整型或者浮点型;甚至是二进制流数据,例如图片、音频、视频等。不过一个字符串的最大值不能超过 512 MB。
由于 Redis 内部存储字符串完全是按照二进制流的形式保存的,所以 Redis 是不处理字符集编码问题的,客户端传入的命令中使用的是什么字符集编码,就存储什么字符集编码。
常见命令
SET
将 string 类型的 value 设置到 key 中。如果 key 之前存在,则覆盖,无论原来的数据类型是什么。之前关于此 key 的 TTL 也全部失效。
语法:
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
命令有效版本:1.0.0 之后
时间复杂度:O(1)
选项:
- EX seconds —— 使用秒作为单位设置 key 的过期时间。
- PX milliseconds —— 使用毫秒作为单位设置 key 的过期时间。
- NX —— 只在 key 不存在时才进行设置,即如果 key 之前已经存在,设置不执行。
- XX —— 只在 key 存在时才进行设置,即如果 key 之前不存在,设置不执行。
注意:由于带选项的 SET 命令可以被 SETNX、SETEX、PSETEX 等命令代替,所以之后的版本中,Redis 可能进行合并。
返回值: - 如果设置成功,返回 OK。
- 如果由于 SET 指定了 NX 或者 XX 但条件不满足,SET 不会执行,并返回 (nil)。
示例:
redis> EXISTS mykey
(integer) 0
redis> SET mykey "Hello"
OK
redis> GET mykey
"Hello"
redis> SET mykey "World" NX
(nil)
redis> DEL mykey
(integer) 1
redis> EXISTS mykey
(integer) 0
redis> SET mykey "World" XX
(nil)
redis> GET mykey
(nil)
redis> SET mykey "World" NX
OK
redis> GET mykey
"World"
redis> SET mykey "Will expire in 10s" EX 10
OK
redis> GET mykey
"Will expire in 10s"
# 10秒之后
redis> GET mykey
(nil)
GET
获取 key 对应的 value。如果 key 不存在,返回 nil。如果 value 的数据类型不是 string,会报错。
语法:
GET key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:key 对应的 value,或者 nil 当 key 不存在。
示例:
redis> GET nonexisting
(nil)
redis> SET mykey "Hello"
"OK"
redis> GET mykey
"Hello"
redis> DEL mykey
(integer) 1
redis> EXISTS mykey
(integer) 0
redis> HSET mykey name Bob
(integer) 1
redis> GET mykey
(error) WRONGTYPE Operation against a key holding the wrong kind of value
MGET
一次性获取多个 key 的值。如果对应的 key 不存在或者对应的数据类型不是 string,返回 nil。
语法:
MGET key [key ...]
命令有效版本:1.0.0 之后
时间复杂度:O(N) N 是 key 数量
返回值:对应 value 的列表
示例:
redis> SET key1 "Hello"
OK
redis> SET key2 "World"
OK
redis> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)
MSET
一次性设置多个 key 的值。
语法:
MSET key value [key value ...]
命令有效版本:1.0.1 之后
时间复杂度:O(N) N 是 key 数量
返回值:永远是 OK
示例:
redis> MSET key1 "Hello" key2 "World"
OK
redis> GET key1
"Hello"
redis> GET key2
"World"
如上图所示,使用 mget 由于可以有效地减少网络时间,所以性能相对更高。假设网络耗时 1 毫秒,命令执行 1 毫秒,那么执行时间如下表所示。
100 次 get 和 1 次 mget 100 个键对比
操作 | 时间 |
---|---|
100 次 get | 100 x 1 + 100 x 0.1 = 110 毫秒 |
1 次 mget 100 个键 | 1 x 1 + 100 x 0.1 = 101 毫秒 |
学会使用批量操作,可以有效提高业务处理效率,但是要注意,每次批量操作所发送的键的数量也不是无节制的,否则可能造成单一命令执行时间过长,导致 Redis 阻塞。
SETNX
设置 key-value 但只允许在 key 之前不存在的情况下。
语法:
SETNX key value
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:1 表示设置成功。0 表示没有设置。
示例:
redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"
- set key value :判断 key 是否存在,存在或不存在均设置成功。
- set key value xx :判断 key 是否存在,存在则设置成功,不存在则设置失败。
- set key value nx 或者 setnx key value :判断 key 是否存在,存在则设置失败,不存在则设置成功。
计数命令
INCR
将 key 对应的 string 表示的数字加一。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是一个整型或者范围超过了 64 位有符号整型,则报错。
语法:
INCR key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:integer 类型的加完后的数值。
示例:
redis> EXISTS mykey
(integer) 0
redis> INCR mykey
(integer) 1
redis> SET mykey "10"
OK
redis> INCR mykey
(integer) 11
redis> SET mykey "2342934823904890489209348230948"
OK
redis> INCR mykey
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
OK
redis> INCR mykey
(error) value is not an integer or out of range
INCRBY
将 key 对应的 string 表示的数字加上对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是一个整型或者范围超过了 64 位有符号整型,则报错。
语法:
INCRBY key decrement
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:integer 类型的加完后的数值。
示例:
redis> EXISTS mykey
(integer) 0
redis> INCRBY mykey 3
(integer) 3
redis> SET mykey "10"
OK
redis> INCRBY mykey 3
(integer) 13
redis> INCRBY mykey "not a number"
(error) value is not an integer or out of range
redis> SET mykey "2342934823904890489209348230948"
OK
redis> INCRBY mykey 3
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
OK
redis> INCRBY mykey 3
(error) value is not an integer or out of range
DECR
将 key 对应的 string 表示的数字减一。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是一个整型或者范围超过了 64 位有符号整型,则报错。
语法:
DECR key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:integer 类型的减完后的数值。
示例:
redis> EXISTS mykey
(integer) 0
redis> DECR mykey
(integer) -1
redis> SET mykey "10"
OK
redis> DECR mykey
(integer) 9
redis> SET mykey "2342934823904890489209348230948"
OK
redis> DECR mykey
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
OK
redis> DECR mykey
(error) value is not an integer or out of range
DECRBY
将 key 对应的 string 表示的数字减去对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是一个整型或者范围超过了 64 位有符号整型,则报错。
语法:
DECRBY key decrement
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:integer 类型的减完后的数值。
示例:
redis> EXISTS mykey
(integer) 0
redis> DECRBY mykey 3
(integer) -3
redis> SET mykey "10"
OK
redis> DECRBY mykey 3
(integer) 7
redis> DECRBY mykey "not a number"
(error) value is not an integer or out of range
redis> SET mykey "2342934823904890489209348230948"
OK
redis> DECRBY mykey 3
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
OK
redis> DECRBY mykey 3
(error) value is not an integer or out of range
INCRBYFLOAT
将 key 对应的 string 表示的浮点数加上对应的值。如果对应的值是负数,则视为减去对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的不是 string,或者不是一个浮点数,则报错。允许采用科学计数法表示浮点数。
语法:
INCRBYFLOAT key increment
命令有效版本:2.6.0 之后
时间复杂度:O(1)
返回值:加/减完后的数值。
示例:
redis> SET mykey 10.50
OK
redis> INCRBYFLOAT mykey 0.1
"10.6"
redis> INCRBYFLOAT mykey -5
"5.6"
redis> SET mykey 5.0e3
OK
redis> INCRBYFLOAT mykey 2.0e2
"5200"
很多存储系统和编程语言内部使用 CAS 机制实现计数功能,会有一定的 CPU 开销,但在 Redis 中完全不存在这个问题,因为 Redis 是单线程架构,任何命令到了 Redis 服务端都要顺序执行。
其他命令
APPEND
如果 key 已经存在并且是一个 string,命令会将 value 追加到原有 string 的后边。如果 key 不存在,则效果等同于 SET 命令。
- 语法:APPEND KEY VALUE
- 命令有效版本:2.0.0 之后
- 时间复杂度:O(1),追加的字符串一般长度较短,可视为 O(1)
- 返回值:追加完成之后 string 的长度
- 示例:
redis> EXISTS mykey
(integer) 0
redis> APPEND mykey "Hello"
(integer) 5
redis> GET mykey
"Hello"
redis> APPEND mykey " World"
(integer) 11
redis> GET mykey
"Hello World"
GETRANGE
返回 key 对应的 string 的子串,由 start 和 end 确定(左闭右闭)。可以使用负数表示倒数,-1 代表倒数第一个字符,-2 代表倒数第二个,其他的与此类似。超过范围的偏移量会根据 string 的长度调整成正确的值。
- 语法:GETRANGE key start end
- 命令有效版本:2.4.0 之后
- 时间复杂度:O(N),N 为 [start, end] 区间的长度,由于 string 通常较短,可视为 O(1)
- 返回值:string 类型的子串
- 示例:
redis> SET mykey "This is a string"
OK
redis> GETRANGE mykey 0 3
"This"
redis> GETRANGE mykey -3 -1
"ing"
redis> GETRANGE mykey 0 -1
"This is a string"
redis> GETRANGE mykey 10 100
"string"
SETRANGE
覆盖字符串的一部分,从指定的偏移开始。
- 语法:SETRANGE key offset value
- 命令有效版本:2.2.0 之后
- 时间复杂度:O(N),N 为 value 的长度,由于一般给的 value 较短,通常视为 O(1)
- 返回值:替换后的 string 的长度
- 示例:
redis> SET key1 "Hello World"
OK
redis> SETRANGE key1 6 "Redis"
(integer) 11
redis> GET key1
"Hello Redis"
STRLEN
获取 key 对应的 string 的长度。当 key 存放的类似不是 string 时,报错。
- 语法:STRLEN key
- 命令有效版本:2.2.0 之后
- 时间复杂度:O(1)
- 返回值:string 的长度。或者当 key 不存在时,返回 0
- 示例:
redis> SET mykey "Hello world"
OK
redis> STRLEN mykey
(integer) 11
redis> STRLEN nonexisting
(integer) 0
命令小结
命令 | 执行效果 | 时间复杂度 |
---|---|---|
set key value [key value…] | 设置 key 的值是 value | O(k),k 是键个数 |
get key | 获取 key 的值 | O(1) |
del key [key …] | 删除指定的 key | O(k),k 是键个数 |
mset key value [key value …] | 批量设置指定的 key 和 value | O(k),k 是键个数 |
mget key [key …] | 批量获取 key 的值 | O(k),k 是键个数 |
incr key | 指定的 key 的值 +1 | O(1) |
decr key | 指定的 key 的值 -1 | O(1) |
incrby key n | 指定的 key 的值 +n | O(1) |
decrby key n | 指定的 key 的值 -n | O(1) |
incrbyfloat key n | 指定的 key 的值 +n(浮点数运算) | O(1) |
append key value | 指定的 key 的值追加 value | O(1) |
strlen key | 获取指定 key 的值的长度 | O(1) |
setrange key offset value | 覆盖指定 key 的从 offset 开始的部分值 | O(n),n 是字符串长度,通常视为 O(1) |
getrange key start end | 获取指定 key 的从 start 到 end 的部分值 | O(n),n 是字符串长度,通常视为 O(1) |
内部编码
字符串类型的内部编码有 3 种:
- emb:8 个字节的长整型。
- embstr:小于等于 39 个字节的字符串。
- raw:大于 39 个字节的字符串。
Redis 会根据当前值的类型和长度动态决定使用哪种内部编码实现。 - 整型示例:
127.0.0.1:6379> set key 6379
OK
127.0.0.1:6379> object encoding key
"int"
- 短字符串示例:
# 小于等于 39 个字节的字符串
127.0.0.1:6379> set key "hello"
OK
127.0.0.1:6379> object encoding key
"embstr"
- 长字符串示例:
# 大于 39 个字节的字符串
127.0.0.1:6379> set key "one string greater than 39 bytes ......."
OK
127.0.0.1:6379> object encoding key
"raw"
典型使用场景
- 缓存(Cache)功能
- 计数(Counter)功能
- 共享会话(Session)
- ⼿机验证码