springboot使用redis,用scan实现keys * 的功能

@GetMapping(value = "/patternDelete")
    public Set<String> patternDeleteCache(String pattern) {
        Set<String> deleteKeys = (Set<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            ScanOptions scanOptions = ScanOptions.scanOptions().match("*" + pattern + "*").count(1000).build();
            Cursor<byte[]> scan = connection.scan(scanOptions);
            Set<String> keys = new HashSet<>();
            while (scan.hasNext()) {
                byte[] next = scan.next();
                keys.add(new String(next));
            }
            return keys;
        });
        if (CollectionUtils.isNotEmpty(deleteKeys)) {
            redisTemplate.delete(deleteKeys);
        }
        return deleteKeys;
    }

参考在RedisTemplate中使用scan代替keys指令

Spring Boot使用Redis缓存时,可能会遇到使用`keys`命令报错的情况。这是因为`keys`命令在Redis中是一个阻塞操作,特别是在数据量较大时,会导致Redis服务器的性能下降。因此,Redis官方建议在生产环境中避免使用`keys`命令。 以下是一些解决方案和替代方法: ### 1. 使用`SCAN`命令替代`KEYS` `SCAN`命令是一个增量迭代器,可以逐步扫描Redis中的键,而不会阻塞服务器。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisCallback; 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 List<String> scanKeys(String pattern) { List<String> keys = new ArrayList<>(); redisTemplate.execute((RedisCallback<Void>) connection -> { Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(pattern).count(1000).build()); while (cursor.hasNext()) { keys.add(new String(cursor.next())); } cursor.close(); return null; }); return keys; } } ``` ### 2. 使用Redis的键空间通知 键空间通知允许应用程序监听Redis中的键事件,从而在键被创建或删除时得到通知。 ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; @Configuration public class RedisListenerConfig { @Bean public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); container.addMessageListener(listenerAdapter, new PatternTopic("__keyevent@0__:del")); return container; } @Bean public MessageListenerAdapter listenerAdapter() { return new MessageListenerAdapter(new RedisKeyEventListener()); } } ``` ### 3. 使用Redis的`SET`操作 在设计缓存时,尽量使用`SET`操作来管理键,而不是依赖`KEYS`命令。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @Service public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; public void setKey(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object getKey(String key) { return redisTemplate.opsForValue().get(key); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值