掘金 后端 ( ) • 2024-04-16 18:56

highlight: a11y-dark theme: juejin

1.Redis 的常用命令

1.1 基本全局命令

  1. keys
keys pattern

返回所有满⾜样式(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 和 hbllo
  1. exists
  • 判断某个key是否存在。
  • 返回 key 存在的个数
exists key [key ...]
  1. del
  • 删除 key
del key [key ...]
  1. expire
  • 设置过期时间(以秒为单位)
expire key seconds
  1. ttl
  • 获取指定 key 的过期时间(以秒为单位)
  • 返回值:剩余过期时间。-1表⽰没有关联过期时间,-2表⽰key不存在。
ttl key
  1. type
  • 返回 key 对应 value 的数据类型。
  • 返回:none , string , list , set , zset , hash。
type key
  1. object encoding
  • 返回对应 key 的内部编码
object encoding key

image-20240414224111858

  1. flushall
  • 一键清空所有的键值对,谨慎使用。
flushall

1.2 String数据结构

字符串类型是Redis最基础的数据类型,字符串类型的值实际可以是字符串,包含⼀般格式的字符串或者类似JSONXML格式的字符串;数字,可以是整型或者浮点型;甚⾄是⼆进制流数据,例如图⽚、⾳频、视频等。不过⼀个字符串的最⼤值不能超过512MB

image-20240415111247076

  1. set
  • string类型的value设置到key中。如果key之前存在,则覆盖,⽆论原来的数据类型是什么。之前关于此keyTTL也全部失效。
    • EX seconds⸺使⽤秒作为单位设置key的过期时间。
    • PX milliseconds⸺使⽤毫秒作为单位设置key的过期时间。
    • NX ⸺只在key不存在时才进⾏设置,即如果key之前已经存在,设置不执⾏。
    • XX ⸺只在key存在时才进⾏设置,即如果key之前不存在,设置不执⾏
set key value [expiration EX seconds|PX milliseconds] [NX|XX]

直接设置超时: image-20240415104126374

  1. get
  • 获取key对应的value。如果key不存在,返回nil。如果value的数据类型不是string,会报错。
get key
  1. mget
  • ⼀次性获取多个key的值。如果对应的key不存在或者对应的数据类型不是string,返回nil
mget key [key ……]

image-20240415104751816

  1. mset
  • 一次性设置多个 key
MSET key value [key value ...]
  1. setnx
  • 设置key-value但只允许在key之前不存在的情况下。
setnx key value

image-20240415105333750

  1. incr
  • key对应的string表⽰的数字加⼀。如果key不存在,则视为key对应的value0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。
incr key

image-20240415105720284

  1. incrby
  • key对应的string表⽰的数字加上对应的值。如果key不存在,则视为key对应的value0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。
incrby key decrement

image-20240415105954196

  1. decr
  • key对应的string表⽰的数字减⼀。如果key不存在,则视为key对应的value0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。
decr key
  1. decrby
  • key对应的string表⽰的数字减去对应的值。如果key不存在,则视为key对应的value0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。
decrby key decrement
  1. incrbyfloat
  • key对应的string表⽰的浮点数加上对应的值。如key不存在,则视为key对应的value是0。如果key对应的不是string,或者不是⼀个浮点数,则报错。允许采⽤科学计数法表⽰浮点数。
incrbyfloat key increment

image-20240415110723124

  1. append
  • 如果 key 已经存在并且是⼀个 string,命令会将 value 追加到原有 string 的后边。如果 key 不存在,则效果等同于 SET 命令。
append key value
  1. getreange
  • 返回 key 对应的 string 的⼦串,由 start 和 end 确定(左闭右闭)。可以使⽤负数表⽰倒数。-1代表倒数第⼀个字符,-2代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据 string 的⻓度调整成正确的值。
getrange key start end

image-20240415112156821

  1. setreange
  • 覆盖字符串的⼀部分,从指定的偏移开始。
setreange key offset value

image-20240415112513398

  1. strlen
  • 获取key对应的string的⻓度。
strlen key
  1. 内部编码

字符串类型的内部编码有3种:

  • int:8个字节的⻓整型。
  • embstr:⼩于等于39个字节的字符串。
  • raw:⼤于39个字节的字符串。

Redis会根据当前值的类型和⻓度动态决定使⽤哪种内部编码实现。

image-20240415121202198

1.3 Hash哈希

在 Redis 中,哈希类型是指值本⾝⼜是⼀个键值对结构,形如 key="key",value={{field1,value1},...,{fieldN,valueN}},Redis 键值对和哈希类型⼆者的关系可以⽤下图来表⽰:

image-20240415114108186

哈希类型中的映射关系通常称为field-value,⽤于区分Redis整体的键值对(key-value)。

  1. hset
  • 设置hash中指定的字段(field)的值(value)。
hset key field value [field value ...]

image-20240415114456073

  1. hget
  • 获取 hash 中指定字段的值
hget key field
  1. hexists
  • 判断 hash 中是否有指定的字段
hexists key field

image-20240415114647909

  1. hdel
  • 删除 hash 中的字段
hdel key field [field ...]

image-20240415114825896

  1. hkeys
  • 获取 hash 中所有的字段
hkeys key

image-20240415115155082

  1. hvals
  • 获取 hash 中的所有的值
hvals key

image-20240415115322807

  1. hgetall
  • 获取 hash 所有字段以及对应的值
hgetall key

image-20240415115418045

  1. hmget
  • 一次获取 hash 中多个字段的值
hmget key field [field ...]

image-20240415115647486

  1. hlen
  • 获取 hash 中的所有字段的个数
hlen key
  1. hsetnx
  • 在字段不存在的情况下,设置 hash 中的字段和值。
HSETNX key field value
  1. hincrby
  • 将 hash 中字段对应的数值添加指定的值。
hincrby key field increment
  1. hincrbyfloat
  • 将 hash 中字段对应的数值添加指定的浮点数值。
hincrbyfloat key field increment
  1. 内部编码

两种:

  • ziplist(压缩列表):当哈希类型元素个数⼩于hash-max-ziplist-entries配置(默认512个)、同时所有值都⼩于hash-max-ziplist-value配置(默认64字节)时,Redis会使⽤ziplist作为哈希的内部实现,ziplist使⽤更加紧凑的结构实现多个元素的连续存储,所以在节省内存⽅⾯⽐hashtable更加优秀。

  • hashtable(哈希表):当哈希类型⽆法满⾜ziplist的条件时,Redis会使⽤hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,⽽hashtable的读写时间复杂度为O(1)。

image-20240415133203255

1.4 List列表

列表类型是⽤来存储多个的字符串,⼀个列表最多可以存储 $2^{32} - 1$​ 个元素。

image-20240415164714370

  1. lpush
  • 将一个或者多个元素从左侧放入 list 中
lpush key element [element ...]
  1. lpushx
  • 在key存在时,将⼀个或者多个元素从左侧放⼊(头插)到list中。
lpushx key element [element ...]
  1. rpush
  • 将⼀个或者多个元素从右侧放⼊(尾插)到list中。
RPUSH key element [element ...]
  1. rpushx
  • 在 key 存在时,将⼀个或者多个元素从右侧放⼊(尾插)到 list 中。
rpushx key element [element ...]
  1. lrange
  • 获取从 start 到 end 区间的所有元素,左闭右闭。
lrange key start stop
  1. lpop
  • 从 list 左侧取出元素(即头删)
lpop key
  1. rpop
  • 从list左侧取出元素(即头删)。
rpop key
  1. lindex
  • 获取从左数第 index 位置的元素。
lindex key index
  1. linsert
  • 在特定位置插⼊元素。
LINSERT key <BEFORE | AFTER> pivot element
  • <BEFORE | AFTER>: 指定插入位置,可选的参数,表示在 pivot 元素之前还是之后插入新元素。
  1. llen
  • 获取 list 长度
list key
  1. blpop
  • LPOP的阻塞版本。
BLPOP key [key ...] timeout
  • 如果列表中没有元素,阻塞版本会根据 timeout,阻塞⼀段时间,期间 Redis 可以执⾏其他命令,但要求执⾏该命令的客⼾端会表现为阻塞状态。

image-20240415171456159

  1. brpop
  • RPOP的阻塞版本。
BRPOP key [key ...] timeout
  1. 内部编码
  • ziplist(压缩列表):当列表的元素个数⼩于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的⻓度都⼩于list-max-ziplist-value配置(默认64字节)时,Redis会选⽤ziplist来作为列表的内部编码实现来减少内存消耗。

  • linkedlist(链表):当列表类型⽆法满⾜ziplist的条件时,Redis会使⽤linkedlist作为列表的内部实现。

1.5 Set集合

1.5.1 增删查改命令

集合类型也是保存多个字符串类型的元素的,但和列表类型不同的是,集合中元素之间是⽆序、不允许重复的。Redis 除了⽀持集合内的增删查改操作,同时还⽀持多个集合取交集、并集、差集。

  1. sadd
  • 将⼀个或者多个元素添加到 set 中。
SADD key member [member ...]
  1. smembers
  • 获取⼀个 set 中的所有元素,元素间的顺序是⽆序的。
SMEMBERS key

image-20240415172840867

  1. sismember
  • 判断⼀个元素在不在set中。
SISMEMBER key member
  1. scard
  • 获取set中的元素个数。
scard key

image-20240415173102819

  1. spop
  • 从set中删除并返回⼀个或者多个元素。由于set内的元素是⽆序的,所以取出哪个元素实际是未定义⾏为,即可以看作随机的。
spop key [count]

image-20240415173753346

  1. smove
  • 将⼀个元素从源set取出并放⼊⽬标set中。
SMOVE source destination member

image-20240415174807381

  1. srem
  • 将指定的元素从 set 中删除。
SREM key member [member ...]

1.5.2 Set集合间的操作

  1. sinter
  • 获取给定set的交集中的元素。
SINTER key [key ...]

image-20240415193320254

  1. sinterstore
  • 获取给定 set 的交集中的元素并保存到⽬标set中。
SINTERSTORE destination key [key ...]

image-20240415193545030

  1. sunion
  • 获取给定 set 的并集中的元素。
SUNION key [key ...]

image-20240415193951455

  1. sunionstore
  • 获取给定set的并集中的元素并保存到⽬标set中。
SUNIONSTORE destination key [key ...]

image-20240415194203771

  1. sdiff
  • 获取给定set的差集中的元素。
  • 差集是指从一个集合中去除另一个集合中的所有元素后所得到的集合。假设有集合 A 和集合 B,A 减去 B 的差集表示为 A - B,意思是包含在集合 A 中但不在集合 B 中的所有元素的集合。
SDIFF key [key ...]

image-20240415194800236

  1. sdiffstore
  • 获取给定set的差集中的元素并保存到⽬标set中。
SDIFFSTORE destination key [key ...]

image-20240415194913648

  • intset(整数集合):当集合中的元素都是整数并且元素的个数⼩于 set-max-intset-entries 配置(默认512个)时,Redis 会选⽤ intset 来作为集合的内部实现,从⽽减少内存的使⽤。
  • hashtable(哈希表):当集合类型⽆法满⾜ intset 的条件时,Redis 会使⽤ hashtable 作为集合的内部实现。

1.6 Zset有序集合

它保留了集合不能有重复成员的特点,但与集合不同的是,有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数(score)与之关联,着使得有序集合中的元素是可以维护有序性的,但这个有序不是⽤下标作为排序依据⽽是⽤这个分数。

1.6.1 增删查改

  1. zadd
  • 添加或者更新指定的元素以及关联的分数到zset中,分数应该符合double类型,+inf/-inf为正负极限。
  • XX:仅⽤于更新已经存在的元素,不会添加新元素。
  • NX:仅⽤于添加新元素,不会更新已经存在的元素。
  • GT | LT: 可选参数,用于筛选添加操作,只有分值大于或小于给定分值的成员才会被添加。GT 表示只添加分值大于给定分值的成员,LT 表示只添加分值小于给定分值的成员。
  • INCR:此时命令类似 ZINCRBY 的效果,将元素的分数加上指定的分数。此时只能指定⼀个元素和分数。
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]

image-20240415201925955

zhangsan增加 60

image-20240415202103825

  1. zcard
  • 获取 zset 中的元素个数
zcard key
  1. zcount
  • 返回分数在min和max之间的元素个数,默认情况下,min和max都是包含的。
zcount key min max

image-20240415202357226

  1. zrange
  • 返回指定区间⾥的元素,分数按照升序。加上 WITHSCORES 可以把分数返回。
ZRANGE key min max [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
  • [BYSCORE|BYLEX]:这部分指定范围是由分数(与每个成员关联的数值)还是按字典顺序(成员按字母顺序排序时的顺序)确定的。

  • [REV]:这是一个可选参数。如果指定,则表示结果应以相反的顺序返回(从最高到最低)。

  • [LIMIT offset count]:也是可选的参数,允许你限制返回的结果数量。offset 指定在开始返回元素之前要跳过多少个元素,count 指定要返回的最大元素数。

  • [WITHSCORES]:另一个可选参数。如果指定,Redis 将返回元素及其关联的分数。否则,只返回元素。

image-20240415234549793

注意,这里如果添加了 byscore,那么就是根据分数匹配。

image-20240415234247146

  1. zrevrange
  • 返回指定区间⾥的元素,分数按照降序。带上 WITHSCORES 可以把分数也返回。
ZREVRANGE key start stop [WITHSCORES]
  1. zrangebyscore
  • 返回分数在min和max之间的元素,默认情况下,min和max都是包含的。
ZRANGEBYSCORE key min max [WITHSCORES]
  1. zpopmax
  • 删除并返回分数最⾼的count个元素,如果不写,默认为 1。
ZPOPMAX key [count]

image-20240415235219916

  1. bzpopmax
  • ZPOPMAX的阻塞版本。
BZPOPMAX key [key ...] timeout
  1. zpopmin
  • 删除并返回分数最低的count个元素。
ZPOPMIN key [count]
  1. bzpopmin
  • ZPOPMIN的阻塞版本。
BZPOPMIN key [key ...] timeout
  1. zrank
  • 返回指定元素的排名,升序。
zrank key member

image-20240415235830988

  1. zrevrank
  • 返回指定元素的排名,降序。
ZREVRANK key member
  1. zscore
  • 返回指定元素的分数。
ZSCORE key member
  1. zrem
  • 删除指定的元素
ZREM key member [member ...]
  1. zremrangebyrank
  • 按照排序,升序删除指定范围的元素,左闭右闭。
ZREMRANGEBYRANK key start stop
  1. zremrangebyscore
  • 按照分数删除指定范围的元素,左闭右闭。
ZREMRANGEBYSCORE key min max
  1. zincrby
  • 为指定的元素的关联分数添加指定的分数值。
ZINCRBY key increment member

image-20240416000945853

1.6.2 Zset集合间操作

  1. zinterstore
  • 求出给定有序集合中元素的交集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元素对应的分数按照不同的聚合⽅式和权重得到新的分数。
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
  • destination: 存储交集结果的目标有序集合的键名。
  • numkeys: 这是指定参与交集计算的有序集合的数量。
  • key: 这是参与交集计算的有序集合的键名,可以有一个或多个。
  • [WEIGHTS weight]: 这是一个可选参数,用于指定每个有序集合的权重,权重可以是整数或浮点数,用于对有序集合的分值进行加权计算。
  • [AGGREGATE SUM|MIN|MAX]: 这是另一个可选参数,用于指定计算交集时采用的聚合方式。可以是 SUM(求和)、MIN(最小值)或 MAX(最大值),默认是 SUM。

image-20240416093835824

这个指令表示计算 zset1 和 zset2 两个有序集合的交集,并将结果存储在名为 zset3 的新有序集合中。在计算交集时,zset1 中的分值将乘以 2,zset2 中的分值将乘以 3,并且使用 SUM 聚合函数对交集的分值进行求和(没有写 AGGREGATE 的情况下,默认是 sum)。

  1. zunionstore
  • 求出给定有序集合中元素的并集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元素对应的分数按照不同的聚合⽅式和权重得到新的分数。
zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]

image-20240416094520108

image-20240416094757195

这里与 zinterstore 唯一不同的就是取了并集。

内部编码:

  • ziplist(压缩列表):当有序集合的元素个数⼩于 zset-max-ziplist-entries 配置(默认128个),同时每个元素的值都⼩于 zset-max-ziplist-value 配置(默认64字节)时,Redis 会⽤ ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存的使⽤。

  • skiplist(跳表):当 ziplist 条件不满⾜时,有序集合会使⽤ skiplist 作为内部实现,因为此时 ziplist 的操作效率会下降。

1.9 操作数据库的指令

  1. select
  • 切换数据库
select dbIndex

Redis 默认配置中是有 16 个数据库。select 0 操作会切换到第⼀个数据库,select 15 会切换到最后⼀个数据库。

  1. flushdb/flushall
  • 清除数据库,flushdb 只清除当前数据库,flushall 会清楚所有数 据库。
flushdb/flushall

2.Redis 过期删除策略

Redis 中的过期数据不会在过期时立刻被删除,而是通过以下策略:

  1. 惰性删除:Redis 不会主动地、周期性地检查和删除所有过期的键。惰性删除是指在Redis 访问某个键值时,才会检查该键是否已经过期,如果已过期,则返回 NULL,并同时删除它。
  2. 定期删除:每隔一段时间检查一次数据库,随机删除一些过期键。定期删除在 redis.conf 配置文件中配置如下:hz 10 表示每秒删除10次。

image-20240414215556741

  • 定期删除的过程(每一次):

    • 从过期字典中随机取出 20 个键。
    • 删除这 20 个键中过期的键。
    • 如果过期键的比例超过 25%,重复步骤 1
  • Redis 采用的是惰性与定期相结合的方式。

3.Redis 为什么这么快?

  1. 纯内存操作:Redis 将所有数据存储在内存中,这意味着对数据的读写操作直接在内容中进行,而内存的访问速度远远高于磁盘。
  2. 单线程模型:Redis 使用单线程模型来处理客户端请求。避免了多线程频繁的切换和竞争带来的开销。
  3. I/O 多路复用:Redis 使用了I/O多路复用技术。就是单个线程同时监听多个客户端连接,只有当前网络事件发生时才会进行实际的 I/O 操作,减少等待时间。