springboot3 redis 批量删除特定的 key 或带有特定前缀的 key

在 Spring Boot 3 中与 Redis 一起使用时,可以通过 Redis 的命令来实现批量删除特定的 Key 或带有特定前缀的 Key。以下是实现方式和注意事项。

使用 RedisTemplate

RedisTemplate 是 Spring Boot 提供的一个操作 Redis 的工具,支持各种 Redis 操作。

批量删除指定的 Key

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Set;

@Service
public class RedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void deleteKeys(Set<String> keys) {
        redisTemplate.delete(keys);
    }
}

调用示例:

java 复制代码
@Autowired
private RedisService redisService;

Set<String> keys = Set.of("key1", "key2", "key3");
redisService.deleteKeys(keys);

批量删除特定前缀的 Key

Redis 不直接支持通配符删除,但可以使用 keys 命令获取匹配的 Key,然后删除它们。

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Set;

@Service
public class RedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void deleteKeysWithPrefix(String prefix) {
        // 获取匹配的 key
        Set<String> keys = redisTemplate.keys(prefix + "*");
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
    }
}

调用示例:

java 复制代码
@Autowired
private RedisService redisService;

redisService.deleteKeysWithPrefix("user:"); // 删除所有以 "user:" 开头的 key

注意事项

keys 命令的性能问题:

keys 命令会扫描整个 Redis 数据库,可能会导致性能问题,尤其是数据量较大时。

在生产环境中,推荐使用 SCAN 命令代替 keys。

使用 SCAN 替代 KEYS

SCAN 是一种分段扫描的方式,可以避免一次性加载大量 Key。

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class RedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void deleteKeysWithPrefix(String prefix) {
        List<String> keysToDelete = new ArrayList<>();

        // 使用 SCAN 命令逐步获取匹配的 key
        try (Cursor<byte[]> cursor = redisTemplate.executeWithStickyConnection(
                redisConnection -> redisConnection.scan(ScanOptions.scanOptions().match(prefix + "*").count(1000).build())
        )) {
            if (cursor != null) {
                cursor.forEachRemaining(key -> keysToDelete.add(new String(key)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 删除所有匹配的 key
        if (!keysToDelete.isEmpty()) {
            redisTemplate.delete(keysToDelete);
        }
    }
}

调用示例:

java 复制代码
@Autowired
private RedisService redisService;

redisService.deleteKeysWithPrefix("session:");

使用 Lua 脚本批量删除(推荐)

Lua 脚本可以在 Redis 服务端高效地执行删除操作。

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;

@Service
public class RedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void deleteKeysWithPrefix(String prefix) {
        String script = "local keys = redis.call('keys', ARGV[1]) " +
                        "for i=1,#keys,5000 do " +
                        "  redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) " +
                        "end " +
                        "return keys";
        redisTemplate.execute((RedisConnection connection) -> 
                connection.eval(script.getBytes(), ReturnType.INTEGER, 0, (prefix + "*").getBytes()));
    }
}

总结

小数据集:可以直接使用 keys 和 RedisTemplate 的 delete。

大数据集:推荐使用 SCAN 或 Lua 脚本来批量处理 Key。

生产环境优化:

避免频繁使用通配符操作,建议对 Redis 数据设计时尽量减少需要批量操作的场景。

配合 Redis 的 TTL 自动过期机制,减少手动删除的需求。

相关推荐
凌虚8 小时前
面向 MySQL 用户的 PostgreSQL 快速上手指南
数据库·后端·架构
五阿哥永琪8 小时前
MySQL中操作json的函数!
数据库·mysql·json
来者皆善8 小时前
了解Mysql优化吗?如何优化索引?
数据库·mysql
ai_coder_ai10 小时前
分布式缓存架构设计与实践
分布式·缓存
凡尘——雨落凡尘10 小时前
PHP 线上十大隐形故障复盘:90% 的网站卡顿、502、雪崩,都是这些细节导致的
redis·nginx·php·session
赤壁小虾11 小时前
【渲染流水线】[逐片元阶段]-[透明度测试]以UnityURP为例
java·前端·数据库
MC皮蛋侠客11 小时前
SQLAlchemy 系列(七):高级建模与高效写入——批量 DML、方言与扩展
数据库·python
奈斯先生Vector12 小时前
把 Midjourney 二次编辑做成生产系统:customId 能力令牌、Action Graph 与 WebUI 精修工作台
数据库·人工智能·架构·aigc·音视频·midjourney
Lethehong12 小时前
双擎并驱·全链路并行:KFS让TB级异构增量同步秒级到达
数据库
MC皮蛋侠客12 小时前
SQLAlchemy 系列(八):AsyncIO、并发与 Web 生命周期——让每个并发任务持有自己的 Session
数据库·python