Redis 键管理
键(Key)是Redis中数据的基本单元,本课学习键的管理操作。
键的基本操作
设置键值
REDIS
# 设置字符串
SET user:1 "Alice"
# 设置哈希
HSET user:2 name "Bob" age 30
# 设置列表
LPUSH articles "article1" "article2"
# 设置集合
SADD tags:article1 "redis" "database"
# 设置有序集合
ZADD leaderboard 100 "player1"
获取键值
REDIS
# 获取字符串
GET user:1
# 获取哈希
HGETALL user:2
# 获取列表
LRANGE articles 0 -1
# 获取集合
SMEMBERS tags:article1
# 获取有序集合
ZRANGE leaderboard 0 -1 WITHSCORES
删除键
REDIS
# 删除单个键
DEL user:1
(integer) 1 # 返回删除的键数量
# 删除多个键
DEL user:2 user:3
(integer) 2
# 删除不存在的键
DEL notexist
(integer) 0
检查键是否存在
REDIS
SET mykey "hello"
EXISTS mykey
(integer) 1 # 存在
EXISTS notexist
(integer) 0 # 不存在
# 检查多个键(返回存在的键数量)
EXISTS mykey mykey2 mykey3
(integer) 1 # 只有mykey存在
查看键的类型
REDIS
SET mystring "hello"
TYPE mystring # string
HSET myhash field "value"
TYPE myhash # hash
LPUSH mylist "a"
TYPE mylist # list
SADD myset "a"
TYPE myset # set
ZADD myzset 1 "a"
TYPE myzset # zset
TYPE notexist # none
键的命名规范
良好的键命名让数据管理更清晰。
推荐格式
业务:对象:ID[:属性]
示例
REDIS
# 用户信息
user:1 # 用户1的基本信息
user:1:profile # 用户1的详细资料
user:1:settings # 用户1的设置
# 文章
article:123 # 文章123的内容
article:123:comments # 文章123的评论列表
article:123:views # 文章123的浏览数
# 购物车
cart:user:1 # 用户1的购物车
# 会话
session:token:abc123 # 会话token
# 缓存
cache:api:user:1 # API缓存:用户1的信息
cache:page:home # 页面缓存:首页
# 锁
lock:order:123 # 订单123的锁
命名建议
| 建议 | 示例 | 说明 |
|---|---|---|
| 使用冒号分隔 | user:1:profile |
清晰的层次结构 |
| 使用有意义的前缀 | cache:, session:, lock: |
区分不同用途 |
| 保持一致性 | user:1, user:2 |
统一格式 |
| 避免过长 | u:1:p |
太短不清晰,太长占内存 |
| 避免特殊字符 | user-1 |
使用连字符或冒号,避免空格等 |
💡 键的长度: 键名会占用内存,建议在清晰和简洁间平衡。常用键可以短一些。
过期时间
Redis可以为键设置过期时间,到期自动删除。
设置过期时间
REDIS
SET session:token123 "user_data"
# 方式1:EXPIRE(秒)
EXPIRE session:token123 3600 # 1小时后过期
# 方式2:EXPIREAT(时间戳,秒)
EXPIREAT session:token123 1700000000
# 方式3:PEXPIRE(毫秒)
PEXPIRE session:token123 3600000
# 方式4:PEXPIREAT(时间戳,毫秒)
PEXPIREAT session:token123 1700000000000
# 方式5:SET时设置过期时间
SET cache:key "value" EX 60 # 60秒后过期
SET cache:key "value" PX 60000 # 60000毫秒后过期
查看过期时间
REDIS
# TTL:返回剩余生存时间(秒)
TTL session:token123
(integer) 3500 # 还剩3500秒
# PTTL:返回剩余生存时间(毫秒)
PTTL session:token123
(integer) 3500000
# 特殊返回值
TTL noexpire
(integer) -1 # 键存在但没有设置过期时间
TTL notexist
(integer) -2 # 键不存在
取消过期时间
REDIS
# PERSIST:移除过期时间,键变为永久
PERSIST session:token123
(integer) 1 # 成功移除
PERSIST notexist
(integer) 0 # 键不存在
过期时间应用场景
| 场景 | 过期时间 | 示例 |
|---|---|---|
| 会话 | 30分钟 | SET session:token "data" EX 1800 |
| 验证码 | 5分钟 | SET code:phone:138xxxx "123456" EX 300 |
| 缓存 | 1小时 | SET cache:api:user:1 "data" EX 3600 |
| 限流 | 1分钟 | SET limit:user:1 "10" EX 60 |
| 分布式锁 | 10秒 | SET lock:resource "locked" NX EX 10 |
⚠️ 注意: 过期时间精度为毫秒,但实际删除可能有延迟(惰性删除 + 定期删除)。
键的重命名
RENAME:重命名键
REDIS
SET oldkey "value"
RENAME oldkey newkey
OK
GET newkey
"value"
GET oldkey
(nil) # oldkey已不存在
⚠️ 注意: 如果newkey已存在,RENAME会覆盖它!
RENAMENX:仅当新键不存在时重命名
REDIS
SET key1 "value1"
SET key2 "value2"
RENAMENX key1 key2
(integer) 0 # key2已存在,重命名失败
GET key1
"value1" # key1仍然存在
GET key2
"value2" # key2未被覆盖
键的迁移
MOVE:移动键到其他数据库
REDIS
# 在DB 0
SET mykey "value"
# 移动到DB 1
MOVE mykey 1
(integer) 1 # 成功
# 切换到DB 1
SELECT 1
OK
GET mykey
"value"
⚠️ 注意: MOVE在集群模式下不可用。
DUMP + RESTORE:序列化和反序列化
REDIS
# 序列化键
SET mykey "hello"
DUMP mykey
# 返回序列化后的二进制数据
# 反序列化到新键
RESTORE newkey 0 "\x00\x05hello\t\x00\xf5\xbd\xba\xab\xdc\xa6\xdec"
OK
MIGRATE:迁移键到其他Redis实例
REDIS
# 将mykey迁移到192.168.1.100:6379
MIGRATE 192.168.1.100 6379 mykey 0 5000
OK
# 参数说明
# MIGRATE host port key destination-db timeout
键的排序
SORT命令可以对列表、集合、有序集合进行排序。
基本排序
REDIS
# 列表排序
LPUSH mylist 3 1 4 1 5 9 2 6
SORT mylist
# 1) "1"
# 2) "1"
# 3) "2"
# 4) "3"
# 5) "4"
# 6) "5"
# 7) "6"
# 8) "9"
# 降序排序
SORT mylist DESC
# 1) "9"
# 2) "6"
# 3) "5"
# ...
# 集合排序
SADD myset 5 2 8 1 9
SORT myset
# 1) "1"
# 2) "2"
# 3) "5"
# 4) "8"
# 5) "9"
按外部值排序
REDIS
# 学生ID列表
LPUSH students "student1" "student2" "student3"
# 学生分数
SET student1:score 85
SET student2:score 92
SET student3:score 78
# 按分数排序
SORT students BY *:score
# 1) "student3" # 78分
# 2) "student1" # 85分
# 3) "student2" # 92分
# 获取外部值
SORT students BY *:score GET *:score
# 1) "78"
# 2) "85"
# 3) "92"
保存排序结果
REDIS
# 排序并保存到新键
SORT mylist DESC STORE sorted_list
(integer) 8
LRANGE sorted_list 0 -1
# 1) "9"
# 2) "6"
# ...
查找键
KEYS:查找匹配的键
REDIS
# 设置一些测试数据
SET user:1 "Alice"
SET user:2 "Bob"
SET user:3 "Charlie"
SET product:1 "iPhone"
SET product:2 "iPad"
# 查找所有键
KEYS *
# 1) "user:1"
# 2) "user:2"
# 3) "user:3"
# 4) "product:1"
# 5) "product:2"
# 查找匹配模式的键
KEYS user:*
# 1) "user:1"
# 2) "user:2"
# 3) "user:3"
KEYS *:1
# 1) "user:1"
# 2) "product:1"
KEYS user:[1-2]
# 1) "user:1"
# 2) "user:2"
⚠️ 警告: KEYS会扫描整个数据库,数据量大时非常慢,生产环境禁用!
SCAN:迭代查找键(推荐)
SCAN是KEYS的安全替代,使用游标迭代。
REDIS
# 开始迭代,返回游标和键列表
SCAN 0
1) "5" # 下一次使用的游标
2) 1) "user:1"
2) "user:2"
# 继续迭代
SCAN 5
1) "0" # 游标为0表示迭代结束
2) 1) "user:3"
2) "product:1"
# 匹配模式
SCAN 0 MATCH user:*
1) "3"
2) 1) "user:1"
2) "user:2"
# 指定每次返回的数量
SCAN 0 COUNT 100
SCAN家族命令
REDIS
# 迭代集合元素
SSCAN myset 0
# 迭代哈希字段
HSCAN myhash 0
# 迭代有序集合元素
ZSCAN myzset 0
💡 SCAN的优势: 不阻塞服务器,可以分批处理大量键。
键空间通知
Redis可以通知客户端键的变化事件。
配置键空间通知
REDIS
# 查看配置
CONFIG GET notify-keyspace-events
1) "notify-keyspace-events"
2) "" # 默认关闭
# 开启所有通知
CONFIG SET notify-keyspace-events AKE
OK
通知类型
| 字符 | 通知类型 | 说明 |
|---|---|---|
| K | Keyspace | 键空间通知(keyspace@ |
| E | Keyevent | 键事件通知(keyevent@ |
| A | All | 所有通知(等同于KE$glsh) |
| $ | String | 字符串命令 |
| l | List | 列表命令 |
| s | Set | 集合命令 |
| h | Hash | 哈希命令 |
| z | Sorted Set | 有序集合命令 |
| x | Expired | 过期事件 |
| e | Evicted | 驱逐事件(内存淘汰) |
订阅通知
REDIS
# 订阅键空间通知(键的所有事件)
SUBSCRIBE __keyspace@0__:mykey
# 订阅键事件通知(某个事件的所有键)
SUBSCRIBE __keyevent@0__:set
示例:监听过期键
REDIS
# 配置:开启过期通知
CONFIG SET notify-keyspace-events Ex
OK
# 客户端1:订阅过期事件
SUBSCRIBE __keyevent@0__:expired
# 客户端2:设置带过期时间的键
SET temp "value" EX 5
# 客户端1收到消息:
# 1) "message"
# 2) "__keyevent@0__:expired"
# 3) "temp" # 过期的键名
键的信息
OBJECT命令
REDIS
SET mykey "hello"
# 查看键的内部编码
OBJECT ENCODING mykey
"embstr"
# 查看引用计数
OBJECT REFCOUNT mykey
(integer) 1
# 查看空闲时间(秒)
OBJECT IDLETIME mykey
(integer) 10
MEMORY命令(Redis 4.0+)
REDIS
SET mykey "hello world hello world hello world"
# 查看键占用的内存
MEMORY USAGE mykey
(integer) 56 # 字节数
# 查看键的内存分配详情
MEMORY STATS
STRLEN:获取字符串长度
REDIS
SET mykey "Hello Redis"
STRLEN mykey
(integer) 11
批量操作
批量设置
REDIS
MSET key1 "value1" key2 "value2" key3 "value3"
OK
批量获取
REDIS
MGET key1 key2 key3
1) "value1"
2) "value2"
3) "value3"
# 包含不存在的键
MGET key1 key2 notexist key3
1) "value1"
2) "value2"
3) (nil)
4) "value3"
批量删除
REDIS
# 删除多个键
DEL key1 key2 key3
(integer) 3
❓ 常见问题
Q KEYS命令为什么慢?
A KEYS需要扫描整个数据库,时间复杂度O(N)。数据量大时会阻塞Redis。使用SCAN代替。
Q 过期键什么时候被删除?
A Redis使用惰性删除 + 定期删除。访问键时检查是否过期,后台定期随机检查部分键。
Q 如何批量删除匹配的键?
A
BASH
redis-cli --scan --pattern "prefix:*" | xargs redis-cli DEL
Q:键名最长能有多少字符? A:理论上无限制,但建议不要太长(占用内存)。
Q 如何统计某种类型的键数量?
A 没有直接命令,需要用SCAN遍历并用TYPE判断。
📖 小节
- 键的基本操作:SET、GET、DEL、EXISTS、TYPE
- 键命名规范:使用冒号分隔,有意义的前缀
- 过期时间:EXPIRE、TTL、PERSIST
- 键查找:KEYS(慎用)、SCAN(推荐)
- 键迁移:MOVE、MIGRATE、DUMP/RESTORE
- 键排序:SORT命令
- 键空间通知:监听键的变化事件
📝 作业
- 命名练习: 为电商网站设计键命名规范(用户、商品、订单、购物车)
- 过期练习: 设置一个带过期时间的键,用TTL查看剩余时间,等待过期后验证
- SCAN练习: 创建100个键,使用SCAN遍历所有键
- 批量操作: 使用MSET批量设置10个键,使用MGET批量获取
下一课
下一课我们将学习 Redis 字符串(上),深入学习字符串的基本操作。



