Redis通用命令: KEYS/EXISTS/TYPE/TTL/DEL键生命周期管理
纲要
前面的命令都绑定特定数据类型,本文的通用命令 则只针对 key 本身操作,与 value 类型无关------无论存的是 string、hash、list 还是 zset,都可以用同一套命令管理。
KEYS pattern:按模式匹配查询key,最常用KEYS *EXISTS key:判断key是否存在,返回1/0TYPE key:查看key对应value的类型TTL key:查看key的剩余存活时间DEL key [key ...]:删除一个或多个键值对
通用命令的定位
Redis 命令
类型相关命令
按 value 类型分组
通用命令
只操作 key,与类型无关
string / hash / list / set / zset
KEYS / EXISTS / TYPE / TTL / DEL
通用命令的共同特征是:参数只有 key,不涉及 value 的内部结构。因此它们对所有数据类型一视同仁。
| 命令 | 语法 | 作用 |
|---|---|---|
KEYS |
KEYS pattern |
查找所有符合给定模式的 key |
EXISTS |
EXISTS key |
检查 key 是否存在 |
TYPE |
TYPE key |
返回 key 所储存的值的类型 |
TTL |
TTL key |
返回 key 的剩余过期时间(秒) |
DEL |
DEL key [key ...] |
删除一个或多个 key |
KEYS 模式匹配
bash
127.0.0.1:6379> KEYS *
1) "myset3"
2) "myset"
3) "name"
4) "age"
5) "001"
6) "myset2"
KEYS * 中的 * 是通配符,匹配任意字符,因此该命令等价于「列出所有 key」------这是日常使用频率最高的 Redis 命令之一。
常用模式:
| 模式 | 含义 | 示例 |
|---|---|---|
KEYS * |
所有 key |
--- |
KEYS user:* |
所有以 user: 开头的 key |
user:1、user:2 |
KEYS *:code |
所有以 :code 结尾的 key |
sms:code |
KEYS ?ame |
? 匹配单个字符 |
name、game |
生产环境警告 :
KEYS *会遍历全部键空间,时间复杂度O(N)。在键数量达百万级的生产环境执行会造成Redis短暂阻塞。应改用SCAN命令做增量式遍历。
EXISTS 判断存在性
bash
127.0.0.1:6379> EXISTS name
(integer) 1
127.0.0.1:6379> EXISTS abc
(integer) 0
| 返回值 | 含义 |
|---|---|
1 |
key 存在 |
0 |
key 不存在 |
TYPE 查看值类型
bash
127.0.0.1:6379> TYPE name
string
127.0.0.1:6379> TYPE myset3
zset
127.0.0.1:6379> TYPE myset2
set
127.0.0.1:6379> TYPE 001
hash
TYPE 返回的是 key 对应的 value 的类型,可能的返回值:
| 返回值 | 对应类型 |
|---|---|
string |
字符串 |
hash |
哈希 |
list |
列表 |
set |
集合 |
zset |
有序集合(sorted set 的简写) |
none |
key 不存在 |
这个命令在排查问题时非常有用------当不确定某个 key 存的是什么结构时,用 TYPE 先确认,再选择对应的操作命令。
TTL 查看剩余存活时间
TTL(Time To Live)返回键值对的剩余存活秒数。
bash
# 未设置过期时间的 key,返回 -1,表示永久有效
127.0.0.1:6379> TTL name
(integer) -1
# 先创建一个带过期时间的 key
127.0.0.1:6379> SETEX test 100 itcast
OK
# 查看剩余时间,随时间递减
127.0.0.1:6379> TTL test
(integer) 82
127.0.0.1:6379> TTL test
(integer) 78
返回值含义:
| 返回值 | 含义 |
|---|---|
-1 |
永久有效,未设置过期时间 |
-2 |
key 不存在或已过期被清理 |
>= 0 |
剩余存活秒数 |
SET key value
TTL = -1
SETEX / EXPIRE
TTL 归零
Redis 自动清理,TTL = -2
DEL key
已创建
永久有效
倒计时中
已过期
已删除
DEL 删除键值对
bash
127.0.0.1:6379> DEL test
(integer) 1
127.0.0.1:6379> DEL name age 001
(integer) 3
127.0.0.1:6379> KEYS *
1) "myset3"
2) "myset"
3) "myset2"
DEL 支持一次删除多个 key,返回值为成功删除的数量。
与
HDEL的区别 :DEL删除整个键值对;HDEL只删除hash内部的某个field,key本身保留。
通用命令速查
key 生命周期
KEYS *
查看有哪些 key
EXISTS key
是否存在
TYPE key
是什么类型
TTL key
还能活多久
DEL key
删除
| 场景 | 使用命令 |
|---|---|
| 想知道 Redis 里存了什么 | KEYS * |
| 不确定某个 key 是否存在 | EXISTS key |
| 忘了某个 key 是什么结构 | TYPE key |
| 验证码还剩多久失效 | TTL key |
| 清理测试数据 | DEL key1 key2 ... |
完整可运行代码
java
package com.itheima.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 演示 Redis 通用命令在 Java 中的对应操作。
* 这些操作全部针对 key,与 value 的具体类型无关。
*/
@SpringBootTest
public class RedisCommonCommandTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 对应 KEYS *:列出所有 key。
*/
@Test
public void testKeys() {
Set<String> keys = redisTemplate.keys("*");
System.out.println("KEYS * -> " + keys);
// 按前缀模式匹配
Set<String> userKeys = redisTemplate.keys("user:*");
System.out.println("KEYS user:* -> " + userKeys);
}
/**
* 对应 EXISTS:判断 key 是否存在。
*/
@Test
public void testExists() {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
ops.set("name", "小明");
System.out.println("EXISTS name -> " + redisTemplate.hasKey("name"));
System.out.println("EXISTS abc -> " + redisTemplate.hasKey("abc"));
}
/**
* 对应 TYPE:查看 key 对应 value 的类型。
*/
@Test
public void testType() {
redisTemplate.opsForValue().set("name", "小明");
redisTemplate.opsForHash().put("001", "name", "小明");
redisTemplate.opsForList().leftPush("mylist", "a");
redisTemplate.opsForSet().add("myset", "a");
redisTemplate.opsForZSet().add("myzset", "a", 1.0);
System.out.println("TYPE name -> " + redisTemplate.type("name"));
System.out.println("TYPE 001 -> " + redisTemplate.type("001"));
System.out.println("TYPE mylist -> " + redisTemplate.type("mylist"));
System.out.println("TYPE myset -> " + redisTemplate.type("myset"));
System.out.println("TYPE myzset -> " + redisTemplate.type("myzset"));
System.out.println("TYPE 不存在 -> " + redisTemplate.type("notExistKey"));
}
/**
* 对应 TTL:查看剩余存活时间。
*/
@Test
public void testTtl() throws InterruptedException {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
// 永久有效的 key,TTL 返回 -1
ops.set("name", "小明");
System.out.println("TTL name(永久)-> " + redisTemplate.getExpire("name"));
// 带过期时间的 key
ops.set("test", "itcast", 100, TimeUnit.SECONDS);
System.out.println("TTL test -> " + redisTemplate.getExpire("test") + " 秒");
Thread.sleep(2000);
System.out.println("2 秒后 TTL test -> " + redisTemplate.getExpire("test") + " 秒");
// 已过期的 key,TTL 返回 -2
System.out.println("TTL 不存在的 key -> " + redisTemplate.getExpire("notExistKey"));
}
/**
* 对应 DEL:删除一个或多个 key。
*/
@Test
public void testDel() {
redisTemplate.opsForValue().set("name", "小明");
redisTemplate.opsForValue().set("age", "20");
redisTemplate.opsForHash().put("001", "name", "小明");
System.out.println("删除前 -> " + redisTemplate.keys("*"));
Long count = redisTemplate.delete("name", "age", "001");
System.out.println("DEL 删除数量 -> " + count);
System.out.println("删除后 -> " + redisTemplate.keys("*"));
}
/**
* 生产环境安全遍历:使用 SCAN 替代 KEYS。
*/
@Test
public void testScan() {
try (Cursor<String> cursor = redisTemplate.scan(ScanOptions.scanOptions()
.match("user:*")
.count(100)
.build())) {
while (cursor.hasNext()) {
System.out.println("SCAN 命中 -> " + cursor.next());
}
} catch (Exception e) {
System.err.println("遍历失败:" + e.getMessage());
}
}
}
需要补充的 import:
java
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
工程目录结构
txt
springdataredis_demo/
├── pom.xml
└── src/
├── main/
│ ├── java/com/itheima/
│ │ ├── App.java # 启动类
│ │ └── config/
│ │ └── RedisConfig.java # 序列化器配置
│ └── resources/
│ └── application.yml
└── test/
└── java/com/itheima/test/
└── RedisCommonCommandTest.java
API 速览
Redis 命令 |
RedisTemplate 对应方法 |
返回值说明 |
|---|---|---|
KEYS pattern |
keys(pattern) |
匹配的 key 集合 |
EXISTS key |
hasKey(key) |
true 存在 / false 不存在 |
TYPE key |
type(key) |
DataType 枚举,不存在返回 NONE |
TTL key |
getExpire(key) |
-1 永久、-2 不存在、其余为剩余秒数 |
DEL key... |
delete(key...) |
成功删除的数量 |
EXPIRE key sec |
expire(key, timeout, unit) |
true / false |
SCAN cursor |
scan(options) |
Cursor,用于安全遍历 |
RENAME old new |
rename(oldKey, newKey) |
无返回值 |
getExpire(key)默认返回单位为秒。如需毫秒级精度,使用getExpire(key, TimeUnit.MILLISECONDS)。
官方文档
- Redis 通用命令(Keys 组):https://redis.io/commands/?group=generic
- KEYS 命令:https://redis.io/commands/keys/
- SCAN 命令:https://redis.io/commands/scan/
- TTL 命令:https://redis.io/commands/ttl/
- Spring Data Redis 文档:https://docs.spring.io/spring-data/redis/docs/current/reference/html/
总结
通用命令的共同点是只操作 key 而不关心 value 结构,因此适用于所有数据类型。KEYS * 用于盘点键空间,但在生产环境应替换为 SCAN 以避免阻塞;EXISTS 返回 1/0 判断存在性;TYPE 返回 value 的类型,是排查「这个 key 到底存的是什么」的首选命令;TTL 的 -1 表示永久、-2 表示不存在或已过期、非负值即剩余秒数;DEL 支持批量删除并返回实际删除数量,需注意与只删 field 的 HDEL 区分。