批量操作Redis缓存Key,避免使用keys命令

1、 双重判断加锁的懒汉式Bean

package com.XXX.cloud.platfrom.common.redis.util;

import com.XXX.cloud.common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.ConvertingCursor;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.util.HashSet;
import java.util.Set;

/**
 * @Description: redis缓存key操作工具类
 * @ClassName: RedisKeyUtils
 * @Date: 2020/4/29 8:53
 * @Version: 1.0
 */
@Slf4j
public class RedisKeyBean {

    private RedisTemplate<String, Object> redisTemplate;

    private static RedisKeyBean redisKeyBean = null;

    private RedisKeyBean(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 双重判断加锁的懒汉式
     * @param redisTemplate
     * @date 2020/4/29 9:29
     * @version 1.0
     */
    public static RedisKeyBean getInstance(RedisTemplate<String, Object> redisTemplate) {
        if (redisKeyBean == null) {
            synchronized (RedisKeyBean.class) {
                if (redisKeyBean == null) {
                    redisKeyBean = new RedisKeyBean(redisTemplate);
                }
            }
        }
        return redisKeyBean;
    }

    /**
     * 根据preKey前缀获取redis的缓存key
     * @param preKey
     * @date 2020/4/29 9:14
     * @version 1.0
     */
    public Set<String> scanRedisKeys(String preKey) {
        try {
            long start = System.currentTimeMillis();
            // 需要匹配的key
            String patternKey = preKey + "*";
            ScanOptions options = ScanOptions.scanOptions()
                    // 这里指定每次扫描key的数量(很多博客瞎说要指定Integer.MAX_VALUE,这样的话跟keys有什么区别)
                    .count(10000)
                    .match(patternKey).build();
            RedisSerializer<String> redisSerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
            Cursor cursor = (Cursor) redisTemplate.executeWithStickyConnection(redisConnection -> new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize));
            Set<String> result = new HashSet<>();
            while(cursor.hasNext()){
                result.add(cursor.next().toString());
            }
            // 切记这里一定要关闭,否则会耗尽连接数。报Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisException: Could not get a
            cursor.close();
            log.info("scan扫描共耗时:{}ms,key数量:{}", System.currentTimeMillis()-start, result.size());
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 批量删除preKey前缀的缓存
     * @param preKey
     * @date 2020/4/29 9:21
     * @version 1.0
     */
    public void deleteRedisKeysByPre(String preKey) {
        if (StringUtil.isNotBlank(preKey)) {
            Set<String> redisKeys = scanRedisKeys(preKey);
            redisTemplate.delete(redisKeys);
        }
    }

}

2、调用

// 获取操作缓存key的Bean
RedisKeyBean redisKeyBean = RedisKeyBean.getInstance(redisTemplate);
redisKeyBean.deleteRedisKeysByPre("your preKey");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值