Redis--预备知识以及String类型
目录
一、预备知识
1.1 基本全局命令
1.1.1 KEYS
1.1.2 EXISTS
1.1.3 DEL
1.1.4 EXPIRE
1.1.5 TTL
1.1.6 TYPE
1.2 数据结构以及内部编码
1.3 单线程架构
二、String字符串
2.1 常见命令
2.1.1 SET
2.1.2 GET
2.1.3 MGET
2.1.4 MSET
2.1.5 SETNX
2.2 计数命令
2.2.1 INCR
2.2.2 INCRBY
2.2.3 DECR
2.2.4 DECRBY
2.2.5 INCRBYFLOAT
2.3 其他命令
2.3.1 APPEND
2.3.2 GETRANGE
2.3.3 SETRANGE
2.3.4 STRLEN
Redis 提供了 5 种数据结构,理解每种数据结构的特点对于 Redis 开发运维非常重要,同时掌握每
种数据结构的常见命令,会在使用 Redis 的时候做到游刃有余。
一、预备知识
在正式介绍 5 种数据结构之前,了解⼀下 Redis 的⼀些全局命令、数据结构和内部编码、单线程
命令处理机制是⼗分必要的,它们能为后面内容的学习打下⼀个良好的基础.
主要体现再以下两个方面:
1)Redis 的命令有上百个,如果纯靠死记硬背比较困难,但是如果理解 Redis 的⼀些机制,会发现这些命令有很强的通用性。
2)Redis 不是万金油,有些数据结构和命令必须在特定场景下使用,⼀旦使用不当可能对 Redis 本或者应用本身造成致命伤害。
1.1 基本全局命令
Redis有5种数据结构,但它们都是键值对钟的值,对于键来说有一些通用的命令。
1.1.1 KEYS
返回所有满足样式(pattern)的 key。支持如下统配样式。
h?llo 匹配 hello , hallo 和 hxllo
h*llo 匹配 hllo 和 heeeello
h[ae]llo 匹配 hello 和 hallo 但不匹配 hillo
h[^e]llo 匹配 hallo , hbllo , ... 但不匹配 hello
h[a-b]llo 匹配 hallo 和 hbll
语法:
KEYS pattern
命令有效版本:1.0.0 之后
时间复杂度:O(N)
返回值:匹配 pattern 的所有 key。
1.1.2 EXISTS
判断某个key是否存在
语法:
EXISTS key [key ...]
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:key 存在的个数。
示例:
redis> SET key1 "Hello"
"OK"
redis> EXISTS key1
(integer) 1
redis> EXISTS nosuchkey
(integer) 0
redis> SET key2 "World"
"OK"
redis> EXISTS key1 key2 nosuchkey
(integer) 2
1.1.3 DEL
删除指定的key
语法:
DEL key [key ...]
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:删除掉的 key 的个数。
示例:
redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> DEL key1 key2 key3
(integer) 2
1.1.4 EXPIRE
为指定的key添加秒级的过期时间
语法:
EXPIRE key seconds
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:1 表示设置成功。0表示设置失败
示例:
redis> SET mykey "Hello"
"OK"
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10
1.1.5 TTL
获取指定key的过期时间,秒级
语法:
TTL key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:剩余过期时间。-1 表示没有关联过期时间,-2 表示 key 不存在。
EXPIRE 和 TTL 命令都有对应的支持毫秒为单位的版本:PEXPIRE 和 PTTL。
1.1.6 TYPE
返回key对应的数据类型
语法:
TYPE key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值: none , string , list , set , zset , hash and stream .。
1.2 数据结构以及内部编码
type 命令实际返回的就是当前键的数据结构类型,它们分别是:string(字符串)、list(列
表)、hash(哈希)、set(集合)、zset(有序集合),但这些只是 Redis 对外的数据结构。
实际上 Redis 针对每种数据结构都有自己的底层内部编码实现,而且是多种实现,这样 Redis 会
在合适的场景选择合适的内部编码。
数据结构 | 内部编码 |
string | raw、int、embstr |
hash | hashtable、ziplist |
list | linkedlist、ziplist |
set | hashtable、intset |
zset | skiplist、ziplist |
可以看到每种数据结构都有至少两种以上的内部编码实现,例如 list 数据结构包含了 linkedlist 和
ziplist 两种内部编码。同时有些内部编码,例如 ziplist,可以作为多种数据结构的内部实现,可以通过 object encoding 命令查询内部编码:
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> lpush mylist a b c
(integer) 3
127.0.0.1:6379> object encoding hello
"embstr"
127.0.0.1:6379> object encoding mylist
"quicklist"
可以看到 hello 对应值的内部编码是 embstr,键 mylist 对应值的内部编码是 ziplist。
Redis 这样设计有两个好处:
1)可以改进内部编码,而对外的数据结构和命令没有任何影响,这样⼀旦开发出更优秀的内部编码,无需改动外部数据结构和命令,例如 Redis 3.2 提供了 quicklist,结合了 ziplist 和 linkedlist 两者的优势,为列表类型提供了⼀种更为优秀的内部编码实现,而对用户来说基本无感知。
2)多种内部编码实现可以在不同场景下发挥各自的优势,例如 ziplist 比较节省内存,但是在列表元素比较多的情况下,性能会下降,这时候 Redis 会根据配置选项将列表类型的内部实现转换为
linkedlist,整个过程用户同样无感知。
1.3 单线程架构
Redis 使用了单线程架构来实现高性能的内存数据库服务。
为什么Redis单线程还能那么快?可以将其归结为以下三点:
1)纯内存访问。Redis 将所有数据放在内存中,内存的响应时长大约为 100 纳秒,这是 Redis 达
到每秒万级别访问的重要基础。
2)非阻塞 IO。Redis 使用 epoll 作为 I/O 多路复用技术的实现,再加上 Redis 自身的事件处理模型将 epoll 中的连接、读写、关闭都转换为事件,不在网络 I/O 上浪费过多的时间。
3)单线程避免了线程切换和竞态产生的消耗。单线程可以简化数据结构和算法的实现,让程序模
型更简单;其次多线程避免了在线程竞争同⼀份共享数据时带来的切换和等待消耗。
二、String字符串
字符串类型是 Redis 最基础的数据类型,关于字符串需要特别注意:1)首先 Redis 中所有的键的
类型都是字符串类型,而且其他几种数据结构也都是在字符串类似基础上构建的,例如列表和集合的 元素类型是字符串类型,所以字符串类型能为其他 4 种数据结构的学习奠定基础。2)其次,字符串类型的值实际可以是字符串,包含⼀般格式的字符串或者类似 JSON、XML 格式的字符串;数字,可以是整型或者浮点型;甚至是⼆进制流数据,例如图片、⾳频、视频等。不过⼀个字符
串的最大值不能超过 512 MB。
2.1 常见命令
2.1.1 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)。
2.1.2 GET
获取 key 对应的 value。如果 key 不存在,返回 nil。如果 value 的数据类型不是 string,会报错。
语法:
GET key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:key 对应的 value,或者 nil 当 key 不存在。
2.1.3 MGET
⼀次性获取多个 key 的值。如果对应的 key 不存在或者对应的数据类型不是 string,返回 nil。
语法:
MGET key [key ...]
命令有效版本:1.0.0 之后
时间复杂度:O(N) N 是 key 数量
返回值:对应 value 的列表
2.1.4 MSET
⼀次性设置多个 key 的值。
语法:
MSET key value [key value...]
命令有效版本:1.0.1 之后
时间复杂度:O(N) N 是 key 数量
返回值:永远是 OK
2.1.5 SETNX
设置 key-value 但只允许在 key 之前不存在的情况下。
语法:
SETNX key value
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:1 表示设置成功。0 表示没有设置。
2.2 计数命令
2.2.1 INCR
将 key 对应的 string 表示的数字加⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。
语法:
INCR key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:integer 类型的加完后的数值。
2.2.2 INCRBY
将 key 对应的 string 表示的数字加上对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错
语法:
INCRBY key decrement
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:integer 类型的加完后的数值。
2.2.3 DECR
将 key 对应的 string 表示的数字减⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。
语法:
DECR key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:integer 类型的减完后的数值。
2.2.4 DECRBY
将 key 对应的 string 表示的数字减去对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。
语法:
DECRBY key decrement
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:integer 类型的减完后的数值。
2.2.5 INCRBYFLOAT
将 key 对应的 string 表示的浮点数加上对应的值。如果对应的值是负数,则视为减去对应的值。如果key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的不是 string,或者不是⼀个浮点数,则报错。允许采用科学计数法表示浮点数。
语法:
INCRBYFLOAT key increment
命令有效版本:2.6.0 之后
时间复杂度:O(1)
返回值:加/减完后的数值。
很多存储系统和编程语言内部使用 CAS 机制实现计数功能,会有⼀定的 CPU 开销,但在 Redis 中完全不存在这个问题,因为 Redis 是单线程架构,任何命令到了 Redis 服务端都要顺序执行。
2.3 其他命令
2.3.1 APPEND
如果 key 已经存在并且是⼀个 string,命令会将 value 追加到原有 string 的后边。如果 key 不存在,则效果等同于 SET 命令。
语法:
APPEND KEY VALUE
命令有效版本:2.0.0 之后
时间复杂度:O(1). 追加的字符串⼀般长度较短, 可以视为 O(1).
返回值:追加完成之后 string 的长度。
2.3.2 GETRANGE
返回 key 对应的 string 的子串,由 start 和 end 确定(左闭右闭)。可以使用负数表示倒数。-1 代表倒数第⼀个字符,-2 代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据 string 的长度调整成正确的值。
语法:
1 GETRANGE key start end
命令有效版本:2.4.0 之后
时间复杂度:O(N). N 为 [start, end] 区间的⻓度. 由于 string 通常比较短, 可以视为是 O(1)
返回值:string 类型的子串
2.3.3 SETRANGE
覆盖字符串的⼀部分,从指定的偏移开始。
语法:
SETRANGE key offset value
命令有效版本:2.2.0 之后
时间复杂度:O(N), N 为 value 的长度. 由于⼀般给的 value 比较短, 通常视为 O(1).
返回值:替换后的 string 的长度。
2.3.4 STRLEN
获取 key 对应的 string 的长度。当 key 存放的类似不是 string 时,报错。
语法:
STRLEN key
命令有效版本:2.2.0 之后
时间复杂度:O(1)
返回值:string 的长度。或者当 key 不存在时,返回 0。