String 字符串
字符串类型是 Redis 最基础的数据类型,关于字符串需要特别注意:
1)⾸先 Redis 中所有的键的类型都是字符串类型,⽽且其他⼏种数据结构也都是在字符串类似基础上构建的,例如列表和集合的元素类型是字符串类型,所以字符串类型能为其他 4 种数据结构的学习奠定基础。
2)其次,如图所⽰,字符串类型的值实际可以是字符串,包含⼀般格式的字符串或者类似 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) 选项: SET 命令⽀持多种选项来影响它的⾏为: • EX seconds ⸺ 使⽤秒作为单位设置 key 的过期时间。 • PX milliseconds⸺ 使⽤毫秒作为单位设置 key 的过期时间。 • NX ⸺ 只在 key 不存在时才进⾏设置,即如果 key 之前已经存在,设置不执⾏。 • XX ⸺ 只在 key 存在时才进⾏设置,即如果 key 之前不存在,设置不执⾏。 注意:由于带选项的 SET 命令可以被 SETNX 、 SETEX 、 PSETEX 等命令代替,所以之后的版本 中,Redis 可能进⾏合并。 返回值: • 如果设置成功,返回 OK。 • 如果由于 SET 指定了 NX 或者 XX 但条件不满⾜,SET 不会执⾏,并返回 (nil)。
GET 获取 key 对应的 value。如果 key 不存在,返回 nil。如果 value 的数据类型不是 string,会报错。 语法:GET key
命令有效版本:1.0.0 之后 时间复杂度:O(1) 返回值:key 对应的 value,或者 nil 当 key 不存在。
MGET ⼀次性获取多个 key 的值。如果对应的 key 不存在或者对应的数据类型不是 string,返回 nil。 语法:MGET key [key ...]
命令有效版本:1.0.0 之后 时间复杂度:O(N) N 是 key 数量 返回值:对应 value 的列表
MSET ⼀次性设置多个 key 的值。 语法:MSET key value [key value ...]
命令有效版本:1.0.1 之后 时间复杂度:O(N) N 是 key 数量 返回值:永远是 OK
使⽤ mget / mset 由于可以有效地减少了⽹络时间,所以性能相较更⾼。假设⽹络耗时 1 毫秒,命令执⾏时间耗时 0.1 毫秒。 学会使⽤批量操作,可以有效提⾼业务处理效率,但是要注意,每次批量操作所发送的键的数量也不 是⽆节制的,否则可能造成单⼀命令执⾏时间过⻓,导致 Redis 阻塞。
SETNX 设置 key-value 但只允许在 key 之前不存在的情况下。 语法:SETNX key value
命令有效版本:1.0.0 之后 时间复杂度:O(1) 返回值:1 表⽰设置成功。0 表⽰没有设置。
计数命令
INCR 将 key 对应的 string 表⽰的数字加⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对 应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。 语法:INCR key
命令有效版本:1.0.0 之后 时间复杂度:O(1) 返回值:integer 类型的加完后的数值。
INCRBY 将 key 对应的 string 表⽰的数字加上对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如 果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。 语法:INCRBY key decrement
命令有效版本:1.0.0 之后 时间复杂度:O(1) 返回值:integer 类型的加完后的数值。
DECR 将 key 对应的 string 表⽰的数字减⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对 应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。 语法:DECR key
命令有效版本:1.0.0 之后 时间复杂度:O(1) 返回值:integer 类型的减完后的数值。
DECYBY 将 key 对应的 string 表⽰的数字减去对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如 果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。 语法:DECRBY key decrement
命令有效版本:1.0.0 之后 时间复杂度:O(1) 返回值:integer 类型的减完后的数值。
INCRBYFLOAT 将 key 对应的 string 表⽰的浮点数加上对应的值。如果对应的值是负数,则视为减去对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的不是 string,或者不是⼀个浮点数,则报 错。允许采⽤科学计数法表⽰浮点数。 语法:INCRBYFLOAT key increment
命令有效版本:2.6.0 之后 时间复杂度:O(1) 返回值:加/减完后的数值。
很多存储系统和编程语⾔内部使⽤ CAS 机制实现计数功能,会有⼀定的 CPU 开销,但在 Redis 中完全 不存在这个问题,因为 Redis 是单线程架构,任何命令到了 Redis 服务端都要顺序执⾏。
其他命令
APPEND 如果 key 已经存在并且是⼀个 string,命令会将 value 追加到原有 string 的后边。如果 key 不存在, 则效果等同于 SET 命令。命令: APPEND KEY VALUE
命令有效版本:2.0.0 之后 时间复杂度:O(1). 追加的字符串⼀般⻓度较短, 可以视为 O(1). 返回值:追加完成之后 string 的⻓度。
GETRANGE 返回 key 对应的 string 的⼦串,由 start 和 end 确定(左闭右闭)。可以使⽤负数表⽰倒数。-1 代表 倒数第⼀个字符,-2 代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据 string 的⻓度调整 成正确的值。 语法:GETRANGE key start end
命令有效版本:2.4.0 之后 时间复杂度:O(N). N 为 [start, end] 区间的⻓度. 由于 string 通常⽐较短, 可以视为是 O(1) 返回值:string 类型的⼦串
SETRANGE 覆盖字符串的⼀部分,从指定的偏移开始。 语法:SETRANGE key offset value
命令有效版本:2.2.0 之后 时间复杂度:O(N), N 为 value 的⻓度. 由于⼀般给的 value ⽐较短, 通常视为 O(1). 返回值:替换后的 string 的⻓度。
STRLEN 获取 key 对应的 string 的⻓度。当 key 存放的类似不是 string 时,报错。 语法:STRLEN key
命令有效版本:2.2.0 之后 时间复杂度:O(1) 返回值:string 的⻓度。或者当 key 不存在时,返回 0。
内部编码
字符串类型的内部编码有 3 种: • int:8 个字节的⻓整型。 • embstr:⼩于等于 39 个字节的字符串。 • raw:⼤于 39 个字节的字符串。 Redis 会根据当前值的类型和⻓度动态决定使⽤哪种内部编码实现。
典型使⽤场景
缓存(Cache)功能 图 2-10 是⽐较典型的缓存使⽤场景,其中 Redis 作为缓冲层,MySQL 作为存储层,绝⼤部分请求的数据都是从 Redis 中获取。由于 Redis 具有⽀撑⾼并发的特性,所以缓存通常能起到加速读写和降低后端压⼒的作⽤。
通过增加缓存功能,在理想情况下,每个⽤⼾信息,⼀个⼩时期间只会有⼀次 MySQL 查询,极⼤地提升了查询效率,也降低了 MySQL 的访问数。
计数(Counter)功能 许多应⽤都会使⽤ Redis 作为计数的基础⼯具,它可以实现快速计数、查询缓存的功能,同时数据可以异步处理或者落地到其他数据源。例如视频⽹站的视频播放次数可以使⽤Redis 来完成:⽤⼾每播放⼀次视频,相应的视频播放数就会⾃增 1。
共享会话(Session) ⼀个分布式 Web 服务将⽤⼾的 Session 信息(例如⽤⼾登录信息)保存在各⾃的服务器中,但这样会造成⼀个问题:出于负载均衡的考虑,分布式服务会将⽤⼾的访问请求均衡到不同的服务器上,并且通常⽆法保证⽤⼾每次请求都会被均衡到同⼀台服务器上,这样当⽤⼾刷新⼀次访问是可能会发现需要重新登录,这个问题是⽤⼾⽆法容忍的。
⼿机验证码 很多应⽤出于安全考虑,会在每次进⾏登录时,让⽤⼾输⼊⼿机号并且配合给⼿机发送验证码, 然后让⽤⼾再次输⼊收到的验证码并进⾏验证,从⽽确定是否是⽤⼾本⼈。为了短信接⼝不会频繁访 问,会限制⽤⼾每分钟获取验证码的频率,例如⼀分钟不能超过 5 次。