Java 接入Redis: 通用命令与键管理

Redis通用命令: KEYS/EXISTS/TYPE/TTL/DEL键生命周期管理

纲要

前面的命令都绑定特定数据类型,本文的通用命令 则只针对 key 本身操作,与 value 类型无关------无论存的是 stringhashlist 还是 zset,都可以用同一套命令管理。

  • KEYS pattern :按模式匹配查询 key,最常用 KEYS *
  • EXISTS key :判断 key 是否存在,返回 1 / 0
  • TYPE 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:1user:2
KEYS *:code 所有以 :code 结尾的 key sms:code
KEYS ?ame ? 匹配单个字符 namegame

生产环境警告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 查看剩余存活时间

TTLTime 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 内部的某个 fieldkey 本身保留。

通用命令速查

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)

官方文档

总结

通用命令的共同点是只操作 key 而不关心 value 结构,因此适用于所有数据类型。KEYS * 用于盘点键空间,但在生产环境应替换为 SCAN 以避免阻塞;EXISTS 返回 1/0 判断存在性;TYPE 返回 value 的类型,是排查「这个 key 到底存的是什么」的首选命令;TTL-1 表示永久、-2 表示不存在或已过期、非负值即剩余秒数;DEL 支持批量删除并返回实际删除数量,需注意与只删 fieldHDEL 区分。

相关推荐
Wang's Blog1 小时前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis
Ivanqhz1 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络
qq_2518364572 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程
caoerzhong2 小时前
JeeWMS 开源仓库管理系统全景解读:一套 Java WMS 如何把 WMS/OMS/BMS/TMS 装进同一个系统
java·开源
曹牧3 小时前
Java集合框架:List、ArrayList、Map 和 HashMap
java
顾城猿3 小时前
STOMP 协议
java
骇客野人3 小时前
测试环境MySQL迁移Vastbase(海量数据库)完整改造与落地实施方案
运维·服务器
+VX:Fegn08954 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
需要8264 小时前
MySQL 索引 B+ 树与“查询为什么变慢了
java·spring boot·spring·spring cloud·tomcat