Redis-数据类型

 

使用 Redis 进行设计和开发时,首先应该考虑 Redis 原生支持的哪些数据类型最适合我们的场景。

字符串 string

字符串是 Redis 的基本数据类型之一,事实上,Redis 中所有的 key 都必须是字符串。

127.0.0.1:6379> set "mykey" chengchao
127.0.0.1:6379> get "mykey" 
"chengchao"

get 不存在的 key 返回 nil

127.0.0.1:6379> get yourkey
(nil)

strlen 返回字符串长度:

127.0.0.1:6379> strlen mykey 
(integer) 9

不存在的 key 执行 strlen, 返回 0:

127.0.0.1:6379> strlen yourkey 
(integer) 0
127.0.0.1:6379> get "Extreme Pizza"
"300 Broadway"

使用 append 命令向一个 key 的字符串末尾追加字符串:

127.0.0.1:6379> append "Extreme Pizza" " 10011"
(integer) 18
127.0.0.1:6379> get "Extreme Pizza"
"300 Broadway 10011"

使用 setrange 命令可以覆盖字符串值的一部分:

如果某个 key 已经存在,那么 SET 命令会覆盖之前的值。

如果不希望覆盖,可以使用 exists 命令来测试。

Redis 提供了 setnx 命令(简称不存在时 set),用于原子地、尽在 key 不存在时设置值。如果值设置成功,setnx 返回 1;如果 key 已经存在,返回 0 并且不覆盖原来的值。

set 命令中的 NX 选项与 setnx 一样。相反,set 命令的 XX 选项表示仅在 key 已经存在时才设置值。


127.0.0.1:6379> set chengchao "hello" NX
OK
127.0.0.1:6379> set chengchao "hello" NX
(nil)
127.0.0.1:6379> set chengchao "hello" NX
(nil)
127.0.0.1:6379> get chengchao
"hello"
127.0.0.1:6379> set chengchao "kao" XX
OK
127.0.0.1:6379> GET chengchao
"kao"
127.0.0.1:6379> setnx chengchao "wokao"
(integer) 0
127.0.0.1:6379> get chengchao
"kao"
127.0.0.1:6379> setnx handong "wokao"
(integer) 1
127.0.0.1:6379> setnx handong "wokao"
(integer) 0
127.0.0.1:6379> set handong "wokao2" NX
(nil)
127.0.0.1:6379> set handong2 "wokao2" nx
OK
127.0.0.1:6379> 
127.0.0.1:6379> get handong2
"wokao2"
127.0.0.1:6379> set handong2 "wokao" xx
OK
127.0.0.1:6379> get handong2
"wokao"
127.0.0.1:6379> 

可以使用 msetmget 命令来一次性地设置和获取多个 key 的值

使用 mset 的优点在于整个操作是原子性的,意味着所有的 key 都是在客户机和服务器之间的一次通信中设置的。可以通过使用一个 MSET 节省网络开销。

MSET key value [key value ...]
MGET key [key value ...]

字符串在 Redis 内部的编码方式

Redis 使用了三种不同的编码方式来存储字符串对象,并会根据每个字符串值自动决定使用的编码方式:

  • int : 用于能够使用 64 位有符号整数表示的字符串。
  • embstr : 用于长度小于与或等于 44 字节(3.x 中是 39 字节)的字符串;这种类型的编码在内存使用和性能方面更有效率。
  • raw : 用于长度大于 44 字节的字符串。

使用 object 命令来查看与 key 相关联的 Redis 值对象的内部编码方式:

127.0.0.1:6379> object encoding chengchao
"embstr"
127.0.0.1:6379> set mykey 123
OK
127.0.0.1:6379> object encoding mykey
"int"
127.0.0.1:6379> get mykey
"123"
127.0.0.1:6379> object encoding "extreme Pizza"
"raw"
127.0.0.1:6379> object encoding "Extreme Pizza"
"raw"
127.0.0.1:6379> strlen "Extreme Pizza"
(integer) 21

更多内容:

https://redis.io/commands

列表 (list)

列表能够存储一组对象,因此它也可以被用作栈和队列。

Redis 中,与 key 相关联的值可以是字符串组成的列表。

Redis 中的列表更像数据结构世界中的双向链表。

LPUSH 在列表的左端插入

127.0.0.1:6379> LPUSH favorite_site "PF Chang's" "Olive Garder"
(integer) 2

LRANGE 获取列表中所有数据

127.0.0.1:6379> LRANGE favorite_site 0 -1
1) "Olive Garder"
2) "PF Chang's"

RPUSH 在列表的右端插入数据

127.0.0.1:6379> RPUSH favorite_site "guijie" "nanluoguxiang"
(integer) 4
127.0.0.1:6379> lrange favorite_site 0 -1
1) "Olive Garder"
2) "PF Chang's"
3) "guijie"
4) "nanluoguxiang"
127.0.0.1:6379> 

LINSERT 在指定值后面插入数据

127.0.0.1:6379> LINSERT favorite_site AFTER "guijie" "wo-kao"
(integer) 6
127.0.0.1:6379> lrange favorite_site 0 -1
1) "Olive Garder"
2) "PF Chang's"
3) "guijie"
4) "wo-kao"
5) "wo-kao"
6) "nanluoguxiang"

LINDEX 获取列表中指定索引的值

127.0.0.1:6379> LINDEX favorite_site 3
"wo-kao"

原理

Redis 中的列表与双向链表类似,因此可以使用下面的三个命令将新元素添加到列表中:

  • LPUSH : 将元素添加到列表的左端。
  • RPUSH : 将元素添加到列表的右端。
  • LINSERT : 将元素插入到俩表的支点/枢轴元素(pivotalelement) 之前或之后。

以上命令会返回插入后列表的长度。

想列表插入元素前,无需事先初始化一个空列表。如果我们向一个不存在的 key 中插入元素,Redis 将首先创建换一个空列表并将其与 key 关联。

不需要删除值为空列表的 key, Redis 会自动回收。

如果仅仅想在列表存在时才将元素插入到列表中,那么可以使用 LPUSHXRPUSHX 命令。

可以使用 LPOP 或者 RPOP 从列表中删除一个元素。这两个命令会从列表的左端或右端移除第一个元素并返回其值。当 key 不存在时返回 nil

可以使用 LINDEX 命令从列表中获取谓语指定索引处的元素

可以使用 LRANGE 命令获取一个范围内的元素。

索引的定义

在 Redis 中,假设列表有 n 个元素,则列表的索引可以按照从左到右的方式指定为 0 – n-1; 也可按照从右到左的方式指定为 -1 – -n。因此 0 – -1 就表示整个列表。

LTRIM 命令可用于在删除列表中的多个元素时,只保留由 start 和 end 索引所指定范围内的元素:

127.0.0.1:6379> lrange favorite_site 0 -1
1) "Olive Garder"
2) "PF Chang's"
3) "guijie"
4) "wo-kao"
127.0.0.1:6379> ltirm favorite_site 1 -1
(error) ERR unknown command `ltirm`, with args beginning with: `favorite_site`, `1`, `-1`, 
127.0.0.1:6379> ltrim favorite_site 1 -1
OK
127.0.0.1:6379> lrange favorite_site 0 -1
1) "PF Chang's"
2) "guijie"
3) "wo-kao"
127.0.0.1:6379> 

可以用 LSET 命令设置列表中指定索引位置处元素的值:

127.0.0.1:6379> lrange favorite_site 0 -1
1) "PF Chang's"
2) "guijie"
3) "wo-kao"
127.0.0.1:6379> lset favorite_site 1 gui-jie
OK
127.0.0.1:6379> lrange favorite_site 0 -1
1) "PF Chang's"
2) "gui-jie"
3) "wo-kao"
127.0.0.1:6379> 

更多

LPOPRPOP 命令有对应的阻塞版本:BLPOPBRPOP

与非阻塞版本类似,阻塞版本的命令也从列表的左端或者右端弹出元素;但是当列表为空时,阻塞版本会将客户端阻塞,必须在这些阻塞版本的命令中指定一个以秒为单位的超时时间,表示最长等待多少秒。

当超时时间设置为 0 时,表示永久等待。这个特性在任务调度场景中非常有用:多个任务执行程序会顶戴任务调度程序分派新的任务。任务执行程序秩序要对 Redis 中的列表使用 BLPOPBRPOP,之后每当有新任务时,调度程序把任务插入到列表中,任务执行程序之一变回获取到该任务。

Redis 在内部使用 quicklist 存储列表对象。有两个配置选项可以调整列表对象的存储逻辑:

  • list-max-ziplist-size: 一个列表条目中一个内部节点的最大值(quicklist 的每个节点都是一个 ziplist)。大多数情况下使用默认值即可。
  • list-compress-depth: 列表压缩策略。

如果我们会用到 Redis 中列表首尾的元素, 那么可以利用这个 选项来获得更好的压缩比( 译者注: 该参数表示 quicklist 两端不被压缩的节点的个数,当列表很长的时候最可能被访问的数据 是位于列表两端的数据,因此对这个参数精确地进行调优可以实现 在压缩比和其他因素之间的平衡)。

梅隆魁译. Redis 4.x Cookbook 中文版 (Kindle 位置 799-802). 电子工业出版社. Kindle 版本.

哈希 (hash)

使用 HMSET 命令设置值,HMGET 命令获取多个值

127.0.0.1:6379> get chengchao
"CHENGCHAO"
127.0.0.1:6379> del chengchao
(integer) 1
127.0.0.1:6379> hmset chengchao email "chengchaos@gmail.com" phone 18514026899
OK
127.0.0.1:6379> hmget chengchao
(error) ERR wrong number of arguments for 'hmget' command
127.0.0.1:6379> hmget chengchao email
1) "chengchaos@gmail.com"
127.0.0.1:6379> hmget chengchao email phone
1) "chengchaos@gmail.com"
2) "18514026899"
127.0.0.1:6379> 

使用 HGET 命令从一个哈希中获取某个字段对应的值,HSET 命令设置单个的值

127.0.0.1:6379> get handong
"HANDONG"
127.0.0.1:6379> del handong
(integer) 1
127.0.0.1:6379> hset handong email handong66666@yahoo.com.cn
(integer) 1
127.0.0.1:6379> hget handong email
"handong66666@yahoo.com.cn"

使用 HEXISTS 测试一个哈希中是否存在某个字段;HGETALL 命令获取一个哈希中的所有字段值

127.0.0.1:6379> EXISTS CHENGCHAO
(integer) 0
127.0.0.1:6379> exists chengchao
(integer) 1
127.0.0.1:6379> hexists handong email
(integer) 1
127.0.0.1:6379> hexists handong phone
(integer) 0
127.0.0.1:6379> hgetall handong
1) "email"
2) "handong66666@yahoo.com.cn"
127.0.0.1:6379> 

使用 HDEL 删除哈希中的字段。

工作原理

类似 List,不需要在添加字段前先初始化一个空的哈希。当哈希编程空的时,Redis 会自动将其删除。

默认情况下,HSETHMSET 会覆盖现有的字段。HSETNX 命令则仅在字段不存在的情况下才设置值,可用于防止 HSET 的默认覆盖行为。

对于不存在的 key 或者 field。 HMGET' 和 HGET 将返回 nil` 。

更多细节

一个哈希最多能容纳 2^32 -1 个字段。如果一个哈希的字段非常多,那么执行 HGETALL 命令时可能会阻塞 Redis 服务器。这种情况下,可以使用 HSCAN 来增量地获取所有字段和值。

HSCAN 是 Redis 中 SCAN 命令的一种(SCAN, HSCAN, SSCAN, ZSCAN),该命令会增量地迭代遍历元素,从而不会造成服务器阻塞。

HSCAN 命令时一种基于指针的迭代器,因此我们需要在每次调用命令时指定一个游标(从 0 开始),当一次 HSCAN 运行结束后,Redis 将返回一个元素列表以及一个新的游标,这个游标可用于下一次迭代。

HSCAN 用法:

HSCAN key cursor [MATCH pattern] [COUNT number]
  • 选项 MATCH 用来匹配满足指定 Glob 表达式的字段。
  • 选项 COUNT 说明每次迭代中应该返回多少元素。仅仅是一个参考,默认 10. Redis 不保证返回的元素数量一定是 COUNT 个。
127.0.0.1:6379> HSCAN restaurant 0 MATCH *garden*
1) "309"
2) 1) "panda garden"
   2) "3.9"
   3) "chang's garden"
   4) "4.5"
127.0.0.1:6379> HSCAN restaurant 309 MATCH *garden*
1) "0"
2) 1) "szechuwan garden"
   2) "4.9"

当服务器返回的游标为 0 时,表示整个遍历完成。

存储

Redis 在内部使用两种编码来存储哈希对象

  • ziplist : 对于那些长度小于配置中 hash-max-ziplist-entries 选项配置的值(默认 512),并且所有元素得大小都小于配置中 hash-max-ziplist-value 选项配置的值(默认 64 字节)的哈希,采用此编码。ziplist 编码对于较小的哈希而言可以节省占用空间。
  • hashtable : 当 ziplist 不适用时使用的默认编码。

集合(set)类型

集合类型是由唯一、无序对象组成的集合(collection)。它经常用于测试某个成员是否在集合中、去除重复项、集合运算(并集、交集、差集)。

Redis 的值对象可以是字符串集合。

使用 SADD 命令添加数据

127.0.0.1:6379> sadd tomcat java jsp servlet web cgi
(integer) 5

使用 SISMEMBER 命令测试一个元素是否在集合中

127.0.0.1:6379> sismember tomcat java
(integer) 1
127.0.0.1:6379> sismember tomcat php
(integer) 0

使用 SREM 命令从结合中删除元素

127.0.0.1:6379> srem tomcat web
(integer) 1

使用 SCARD 命令获取集合中成员数量

127.0.0.1:6379> scard tomcat
(integer) 4

工作原理

与列表和哈希类似,Redis 在执行 SADD 命令时,不需要事先准备好一个空集合。同样,Redis 也会自动删除空集合对应的 Key。

更多细节

在 Redis 中,一个集合最多可以容纳 2^32 -1 个成员。

可以使用 SMEMBERS 命令列出集合中的所有元素。但是,类似哈希,在一个大的集合中使用 SMEMBERS 命令可能会阻塞服务器,因此建议此时使用 SSCAN 命令,与哈希的 HSCAN 命令类似。

Redis 提供了一组集合运算相关的命令, SUNIONSUNIONSTORE 用于计算并集;SINTERSINTERSTORE 用于计算交集;SDIFFSDIFFSTORE 用于计算差集。

不带 STORE 后缀的命令只返回相应操作的结果集合,而带 STORE 后缀的命令则会将结果存储到一个指定的 key 中。

127.0.0.1:6379> sadd jetty jsp servlet java
(integer) 3
127.0.0.1:6379> sscan jetty 0 match *
1) "0"
2) 1) "jsp"
   2) "java"
   3) "servlet"
127.0.0.1:6379> smembers tomcat
1) "jsp"
2) "servlet"
3) "java"
4) "cgi"
127.0.0.1:6379> smembers jetty
1) "jsp"
2) "java"
3) "servlet"
127.0.0.1:6379> sinter tomcat jetty
1) "jsp"
2) "java"
3) "servlet"
127.0.0.1:6379> sinterstore common tomcat jetty
(integer) 3
127.0.0.1:6379> smembers common
1) "jsp"
2) "servlet"
3) "java"

存储

Redis 内部使用两种编码凡是来存储集合对象:

  • intset : 对于那些元素都是整数,并且元素个数小于配置中 set-max-intset-entries 选项的值(默认 512)的集合,采用此种编码
  • hashtable : 对于 intset 不适用时的默认编码。

有序集合(storted set)

使用 ZADD 命令添加数据

127.0.0.1:6379> zadd ranking 100 "java" 80 "php" 70 "c++" 90 "c"
(integer) 4

使用 ZREVRANGE 命令获取排名

127.0.0.1:6379> zrevrange ranking 0 -1
1) "java"
2) "c"
3) "php"
4) "c++"
127.0.0.1:6379> zrevrange ranking 0 -1 withscores
1) "java"
2) "100"
3) "c"
4) "90"
5) "php"
6) "80"
7) "c++"
8) "70"

使用 ZINCRBY 命令增加得分

127.0.0.1:6379> zincrby ranking 1 c
"91"
127.0.0.1:6379> zrevrange ranking 0 -1 withscores
1) "java"
2) "100"
3) "c"
4) "91"
5) "php"
6) "80"
7) "c++"
8) "70"

使用 ZREVRANK 命令和 ZSCORE 命令浏览特定的排名和得分

127.0.0.1:6379> zrevrank ranking java
(integer) 0
127.0.0.1:6379> zscore ranking java
"100"
127.0.0.1:6379> zrevrank ranking java2
(nil)

使用 ZUNIONSTORE 合并两个有序集合

工作原理

ZADD 命令中使用 NX 选项,能够实现在不更新有才能在成员的情况下只添加新成员;XX 选项允许不添加新元素的情况先更新集合(只更新存在的成员而不添加新成员)。这些选项只使用与 Redis 3.0.2 及更高版本。

多个不同的成员可能具有相同的权重,此时 Redis 将按照字段顺序进行排序。

ZUNIONSTORE 命令英语将两个有序集合的并集保存到指定的 Key 中,并且可以指定各个有序几个的不同权重。

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] AGGREGATE SUM|MIN|MAX]

存储

Redis 在内部使用两种编码凡是存储有序集合对象:

  • ziplist : 对于那些长度小于配置中 zset-max-ziplist-entries 选项配置的值(默认128),并且素有元素的大小都小于配置中 zset-max-ziplist-value 选型配置的值(默认 64 字节)的有序集合,采用此编码。ziplist 用于节省较小集合所占用的空间
  • skiplist : 当 ziplist 不适用时使用的默认编码。

HyperLogLog 类型

在日常的各种数据处理场景中,“唯一计数”所以一向常见的任务。在 Redis 中,虽然我们可以使用集合来进行唯一计数,但是当数据量增大到上千万是,就需要考虑内存消耗和性能下降的问题了。如果我们不需要获取数据集合的内容,而只是想得到不同值的个数,那么久可以使用 HyperLogLog (HLL) 数据类型来优化使用集合类型时存在的内存和性能问题。

假设需要计算访问 Olive Garden 餐厅的不同客户数:

使用 PFADD 命令吧用户 ID 加入到一个 HyperLogLog 中。然后使用 PFCOUNT 命令获取该餐厅的额不同到访者数量:

127.0.0.1:6379> pfadd "counting:Olive Garden" "0000123"
(integer) 1
127.0.0.1:6379> pfadd "counting:Olive Garden" "0023992"
(integer) 1
127.0.0.1:6379> pfcount "counting:Olive Garden"
(integer) 2
127.0.0.1:6379> 

如果想要展示 Olive Garden 在一个星期中额独立访客数,并将其作为每周流行度的标志,那么,可以每天生成一个 HLL,然后用 PFMERGE 命令把这 7 天的数据合并为一个:

PFADD "Counting:Olive Garden:20170903" "0023992" "0023991" "0045992"
PFADD "Counting:Olive Garden:20170904" "0023992" "0023991" "0045992"
PFADD "Counting:Olive Garden:20170905" "0024492" "0023211" "0045992"
PFADD "Counting:Olive Garden:20170906" "0023999" "0023991" "0045992"
PFADD "Counting:Olive Garden:20170907" "0023992" "0063991" "0045992"
PFADD "Counting:Olive Garden:20170908" "0023292" "0023991" "0045991"
PFADD "Counting:Olive Garden:20170909" "0023282" "0023984" "0045092"


PFMERGE "Counting:Olive Garden:20170903week" "Counting:Olive Garden:20170903" "Counting:Olive Garden:20170904" "Counting:Olive Garden:20170905" "Counting:Olive Garden:20170906" "Counting:Olive Garden:20170907" "Counting:Olive Garden:20170908" "Counting:Olive Garden:20170909"

PFCOUNT "Counting:Olive Garden:20170903week" 



127.0.0.1:6379> PFADD "Counting:Olive Garden:20170903" "0023992" "0023991" "0045992"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170904" "0023992" "0023991" "0045992"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170905" "0024492" "0023211" "0045992"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170906" "0023999" "0023991" "0045992"
Invalid argument(s)
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170907" "0023992" "0063991" "0045992"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170906" "0023999" "0023991" "0045992"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170908" "0023292" "0023991" "0045991"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170909" "0023282" "0023984" "0045092"
(integer) 1
127.0.0.1:6379> PFMERGE "Counting:Olive Garden:20170903week" "Counting:Olive Garden:20170903" "Counting:Olive Garden:20170904" "Counting:Olive Garden:20170905" "Counting:Olive Garden:20170906" "Counting:Olive Garden:20170907" "Counting:Olive Garden:20170908" "Counting:Olive Garden:20170909"
OK
127.0.0.1:6379> PFCOUNT "Counting:Olive Garden:20170903week" 
(integer) 12

工作原理

HHL 类型相关所有命令都是以 PF 开头的,用来向 HLL 数据结构的发明者 Philipe Flajolet 致敬。

Redis 中 HLL 的优势在于能够使用固定数量的内存(每个 HyperLogLog 类型的 Key 只需要占用 128KB 内存,却可以计算最多 2^64 个不同元素的基数)和常熟时间复杂度(每个 Key O(1))进行唯一计数。

不过,由于 HLL 算法返回的基数(HLL 实际是 cardinality counting 基数计算的一种)可能不准确(标准差小于 1%),因此在决定是否使用 HLL时需要进行权衡。

更多细节

(待续)

Geo 类型

(待续)

Key 管理


$ sudo pip install redis fake2db
$ pip
$ sudo apt install python-pip
$ sudo pip install redis fake2db
$ sudo pip install --upgrade pip
$ fake2db --rows 10000 --db redis

获取 Key 的个数

127.0.0.1:6379> DBSIZE
(integer) 50000

获取 Redis 中所有的 Key(1) KEYS

127.0.0.1:6379> KEYS *
...
49997) "user_agent:336"
49998) "detailed_registration:9720"
49999) "detailed_registration:1256"
50000) "company:1084"
(6.89s)

获取 Redis 中所有的 Key(2) SCAN

127.0.0.1:6379> scan 0
1) "57344"
2)  1) "company:2914"
    2) "user_agent:878"
    3) "customer:1063"
    4) "simple_registration:4186"
    5) "customer:1264"
    6) "user_agent:5763"
    7) "detailed_registration:5061"
    8) "company:4318"
    9) "simple_registration:9342"
   10) "simple_registration:3351"
127.0.0.1:6379> scan 57344
1) "61440"
2)  1) "user_agent:8854"
    2) "customer:2289"
    3) "detailed_registration:7221"
    4) "company:1017"
    5) "customer:8992"
    6) "detailed_registration:8530"
    7) "customer:4082"
    8) "user_agent:159"
    9) "simple_registration:3825"
   10) "simple_registration:4324"
   11) "simple_registration:4771"
   12) "company:1112"
127.0.0.1:6379> 

删除 Redis 中的 Key DEL / UNLINK

DELUNLINK (4.0 以上版本)

127.0.0.1:6379> DEL "detailed_registration:1665" "simple_registration:6411"
(integer) 2
127.0.0.1:6379> unlink "company:1664"
(integer) 1

判断一个 Key 是否存在 EXISTS

127.0.0.1:6379> EXISTS "simple_registration:7681"
(integer) 1
127.0.0.1:6379> EXISTS "simple_registration:99999"
(integer) 0

获取数据类型 TYPE


127.0.0.1:6379> TYPE "company:3859"
hash

重命名一个 Key: RENAME

127.0.0.1:6379> RENAME "customer:6591" "customer:6591:renamed"
OK

工作原理

生产环境执行 KEYS * 是一个危险操作, 建议使用 SCAN 替代

另外,对于非字符串数据, 使用个 DEL 命令需要留意, 如果元素数据量很大,可能会导致服务器延迟, 为避免, 应该使用 UNLINK 替代. UNLINK 会在另一个线程而不是主事件循环线程中执行删除操作.

RENAME 命令在目标 Key 存在时会将其删除. 或可能引发 DEL 命令引起的高延迟. 因此, 重命名的最佳实践是: 如果目标 Key 已经存在, 则先对其执行 UNLINK, 然后再重命名.

更多细节

DUMP / RESTORE 命令可以用于序列号和反序列化.可以用这两个命令对 Redis 进行备份工作.

If you like TeXt, don’t forget to give me a star :star2:.