一条泥憨鱼头像
关注
【Redis】通用命令、五大基础数据类型和 Key 的层级管理封面图

【Redis】通用命令、五大基础数据类型和 Key 的层级管理

🌈个人主页:一条泥憨鱼(欢迎各位大佬莅临)

❄️《数据结构》 ❄️《AI与Agent那些事》

❄️《从0开始学计算机网络》 ❄️《后端开发》

前言:

想象你走进一个公共储物柜大厅。每个柜子有编号,你凭编号打开柜子,往里放东西或者取东西。Redis 差不多就是这个意思:一个放在内存里的储物柜仓库,你通过 key 这个编号,去存取对应的 value。

第一次接触 Redis 的话,不用一上来就搞懂集群、持久化、哨兵这些东西。先把最基础的问题弄清楚:怎么开门,怎么存东西,怎么找东西,怎么分类管理。

Redis入门

Redis 是一个键值数据库。

"键值"是什么意思?它存数据的方式特别简单,一个"名字"对应一份"内容"。名字叫 key,内容叫 value。你给 Redis 一个 key,它就还你对应的 value;反过来,你给它一个 key 加一个 value,它就存进去了。

储物柜上贴着标签,标签写"张三的雨伞",柜子里放的就是那把雨伞。这里"张三的雨伞"就是 key,雨伞就是 value。Redis 里也一样:

- key:一个字符串,比如 `user:1:name`

- value:可以是字符串、数字、列表、集合等等(下面会一种一种讲)

那为什么大家都用 Redis?一个字:快。

传统数据库(比如 MySQL)把数据存在硬盘上,每次读写都要跟硬盘打交道,硬盘的速度和内存比差了好几个数量级。Redis 把数据放在内存里,读写几乎就是瞬间的事。代价是内存比硬盘贵,而且断电后内存里的东西会丢——不过 Redis 有持久化机制,那是后话。

现在你只需要记住一件事:Redis 就是一个用 key 找 value 的超高速储物柜。

通用命令——不管什么类型都能用的“万能钥匙”

Redis 的命令有几百个,但有一部分命令不管你存的是什么类型的数据,都能用。这些就是通用命令。先学会它们,你就能开始操作 Redis 了。

KEYS:列出所有 key

KEYS pattern

把所有匹配某个模式的 key 列出来。

# 列出所有 key(危险!后面会说为什么)

KEYS *



# 列出所有以 user: 开头的 key

KEYS user:*

```

踩坑警告:`KEYS *` 在生产环境千万不要用。Redis 是单线程处理命令的,`KEYS *` 会遍历所有 key,如果数据量大了(几十万上百万),这条命令会卡住整个 Redis,其他请求全部排队等着。后面讲 `SCAN` 的时候会给替代方案。

EXISTS:判断 key 存不存在

EXISTS key [key ...]

EXISTS user:1:name

# 返回 1 表示存在,返回 0 表示不存在

DEL:删除 key

DEL key [key ...]

DEL user:1:name

# 返回被删除的 key 数量

EXPIRE 和 TTL:设置过期时间和查看剩余时间

这两个命令经常配对使用。`EXPIRE` 给一个 key 设置"存活时间",到点了 Redis 自动删掉它。`TTL` 用来查看还剩多少时间。

# 设置 user:1:token 这个 key 在 3600 秒后自动删除

EXPIRE user:1:token 3600



# 查看还剩多少秒

TTL user:1:token

# 返回 3595 表示还剩 3595 秒

# 返回 -1 表示没设置过期时间

# 返回 -2 表示 key 已经不存在了

存验证码、临时 token 这类"过一段时间就没用"的数据,用这个功能特别合适。

TYPE:查看 key 是什么类型

TYPE key

TYPE user:1:name

# 返回 string

TYPE user:1

# 可能返回 hash

当你忘了某个 key 存的是什么类型的数据时,`TYPE` 能帮你确认。

Key 的层级格式——用冒号给数据“分文件夹”

Redis 的 key 本质上就是一个字符串,没有真正的目录结构。它不像你电脑里的文件夹可以一层套一层,Redis 里所有 key 都是平铺的。

但大家慢慢形成了一种约定:用冒号 `:` 分隔,模拟出层级的感觉。

比如你要存用户 1 的名字、年龄、邮箱:

user:1:name    -> "张三"

user:1:age     -> "28"

user:1:email   -> "[email protected]"

再比如订单数据:

order:100:status   -> "paid"

order:100:amount   -> "199.00"

order:101:status   -> "pending"

这么做有几个好处。可读性强,你一眼就能看出这个 key 属于哪个业务、哪条记录、哪个字段。要找用户 1 的所有信息,匹配 `user:1:*`;要找所有订单,匹配 `order:*`。不同业务用不同前缀,`user:`、`order:`、`product:`,也不会互相打架。

常见的命名规范大概是这样的:

业务名:对象ID:字段名

或者更细一点:

业务名:对象类型:对象ID:字段名

比如 `shop:product:888:price`。

用 SCAN 代替 KEYS

前面说了 `KEYS *` 在生产环境是禁忌。那怎么安全地找出某一类 key?用 `SCAN`。

`SCAN` 不会一次性返回所有结果,而是分批次返回,每次只返回一小部分。这样就不会长时间阻塞 Redis。

# 从游标 0 开始扫描,每次返回大约 10 个 key,匹配 user:1:*

SCAN 0 MATCH user:1:* COUNT 10

返回结果类似:

1) "17"          <- 下一次扫描的游标

2) 1) "user:1:name"

   2) "user:1:age"

拿到游标 `17` 后,继续用 `SCAN 17 MATCH user:1:* COUNT 10`,直到游标回到 `0`,表示扫完了。

一开始你可能觉得这很麻烦,但记住一点就行:生产环境永远用 SCAN,不用 KEYS。

String 类型——最基础也最万能的“单格储物格”

String 是 Redis 里最简单的类型。一个 key 对应一个字符串值,就像储物柜里只有一个格子,里面放一样东西。

基本存取:SET 和 GET

# 存一个值

SET user:1:name "张三"



# 取出来

GET user:1:name

# 返回 "张三"

就这么简单。存进去什么,取出来就是什么。

SETNX:不存在才设置

SETNX lock:order:100 "1"

# 如果 lock:order:100 不存在,设置成功,返回 1

# 如果已经存在,设置失败,返回 0

`SETNX` 是 "SET if Not eXists" 的缩写。这个命令看起来不起眼,但它能用来做分布式锁的入门版:多个服务同时抢一个锁,谁先 `SETNX` 成功谁就拿到锁,其他人返回 0 就等着。

当然,真正的分布式锁还要考虑过期时间、误删等问题,但 `SETNX` 是理解这件事的起点。

INCR 和 DECR:数字加减

SET page:view:1001 0



INCR page:view:1001

# 返回 1



INCR page:view:1001

# 返回 2



DECR page:view:1001

# 返回 1

```



`INCR` 把值加 1,`DECR` 减 1。

这里有个很重要的点:INCR 是原子操作。意思是,哪怕有一万个请求同时执行 `INCR page:view:1001`,结果也一定是准确的,不会出现两个请求读到同一个值然后各自加 1 导致少算的情况。

这就是为什么 Redis 的 `INCR` 特别适合做计数器——文章阅读量、点赞数、接口调用次数,都可以用它。

MSET 和 MGET:批量存取

# 一次存多个

MSET user:1:name "张三" user:1:age "28" user:1:email "[email protected]"

# 一次取多个

MGET user:1:name user:1:age user:1:email

# 返回:

# 1) "张三"

# 2) "28"

# 3) "[email protected]"

批量操作的好处是减少网络往返次数。存三个值,用 `SET` 要发三次命令,用 `MSET` 只发一次。

Hash 类型——像一个“带多个小格子的抽屉”

String 存一个对象的时候,你得把整个对象序列化成字符串(比如 JSON),改一个字段也要把整个对象读出来、改完再写回去。Hash 解决了这个问题。

Hash 的结构是:一个 key 下面挂多个 field-value 对。就像一个大抽屉里面分了小格子,每个小格子放一个字段。

# 返回:

# 1) "name"

# 2) "张三"

# 3) "age"

# 4) "28"

# 5) "email"

# 6) "[email protected]"



# 删除某个字段

HDEL user:1 email



# 给某个数字字段加值

HINCRBY user:1 age 1

# 返回 29

对比一下:如果用 String 存用户信息,你得 `SET user:1 '{"name":"张三","age":28}'`,改年龄要把整个 JSON 解析出来改完再写回去。用 Hash 直接 `HINCRBY user:1 age 1` 就完事了。

Hash 适合存对象的多个字段,尤其是你经常只读写其中某几个字段的场景。

List 类型——有序、可重复的“排队通道”

List 就是一个有序列表,像排队一样,有头有尾,元素可以重复。

# 从左边塞入

LPUSH queue:task "task1"

LPUSH queue:task "task2"

# 现在列表是:task2, task1



# 从右边塞入

RPUSH queue:task "task3"

# 现在列表是:task2, task1, task3



# 从左边弹出

LPOP queue:task

# 返回 "task2"



# 从右边弹出

RPOP queue:task

# 返回 "task3"



# 查看列表范围(0 到 -1 表示全部)

LRANGE queue:task 0 -1



# 查看长度

LLEN queue:task

List 最典型的用法是消息队列:生产者用 `LPUSH` 从左边塞任务,消费者用 `RPOP` 从右边取任务,先进先出。真正的消息队列要考虑更多东西(确认机制、重试等),但入门级场景完全够用。

另一个常见用法是最新列表。比如"最新 10 条评论",每次来新评论用 `LPUSH` 塞进去,再用 `LTRIM` 保留前 10 个。

Set 类型——无序、不重复的“标签集合”

Set 和 List 最大的区别有两个:无序、不重复。你往里塞重复的元素,它只会保留一个。

# 添加标签

SADD article:1:tags "redis" "database" "cache"



# 再加一个重复的,不会生效

SADD article:1:tags "redis"

# 返回 0,表示没添加新元素



# 查看所有元素

SMEMBERS article:1:tags

# 返回 redis, database, cache(顺序不保证)



# 判断某个元素在不在

SISMEMBER article:1:tags "redis"

# 返回 1



# 删除元素

SREM article:1:tags "cache"

```



Set 真正好用的地方在于集合运算。



```bash

# 用户 1 关注的人

SADD user:1:follows "u2" "u3" "u4"



# 用户 2 关注的人

SADD user:2:follows "u3" "u4" "u5"



# 共同关注(交集)

SINTER user:1:follows user:2:follows

# 返回 u3, u4



# 所有关注(并集)

SUNION user:1:follows user:2:follows

# 返回 u2, u3, u4, u5

共同好友、共同兴趣标签、去重统计,这些场景用 Set 非常自然。

Sorted Set 类型——带排名的“排行榜”

Sorted Set(有序集合)是在 Set 的基础上,给每个元素额外绑了一个分数(score)。Redis 会根据分数自动给元素排序。

# 添加玩家分数

ZADD rank:game 100 "player1"

ZADD rank:game 250 "player2"

ZADD rank:game 180 "player3"



# 按分数从低到高查看(带分数)

ZRANGE rank:game 0 -1 WITHSCORES

# 返回:

# player1, 100

# player3, 180

# player2, 250



# 按分数从高到低查看(排行榜最常用)

ZREVRANGE rank:game 0 -1 WITHSCORES

# 返回:

# player2, 250

# player3, 180

# player1, 100



# 查看某个玩家的分数

ZSCORE rank:game "player2"

# 返回 250



# 查看某个玩家的排名(从低到高,从 0 开始)

ZRANK rank:game "player2"

# 返回 2



# 给某个玩家加分

ZINCRBY rank:game 50 "player1"

# 返回 150

Sorted Set 最经典的用途就是排行榜:游戏得分排名、热搜榜、销量排行。`ZREVRANGE rank:game 0 9` 就能拿到前十名。

它还能用来做延时队列:把任务的执行时间戳作为 score,然后用 `ZRANGEBYSCORE` 取出到时间的任务。

到这里,Redis 最基础的部分过完了。通用命令管理 key,冒号分层组织 key,五种数据类型应付不同的存储需求。

初学把文中的命令挨个敲一遍。敲完之后再去了解过期策略和持久化——那是保证数据不丢的关键,但得先把基础操作练熟了再说。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2503_94545876/article/details/167085432

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--