redis集群实现清理前缀相同的key

 更新时间:2021年10月12日 15:26:53   作者:浮白斋主人  
这篇文章主要介绍了redis集群实现清理前缀相同的key,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

redis集群清理前缀相同的key

最近经常收到redis集群告警,每天收到50多封邮件,实在不胜其烦,内存不够用,原因是有一些无用的key(约3000万)占用内存(具体不说了)。这部分内存不能被释放。

原来的定期清理脚本的逻辑

打开一个redis链接,在内部循环从1000万到7亿之间的数据,然后加上前缀去批量删除,这种方式属于广撒网式的清理,穷举法,不但耗时,效果也不好。

因为有的数字在redis中可能不存在,而且更重要的一点,如果有超过7亿的数字,这部分数据不会被清除,扩展性很差。

(1)那么如何清理呢?redis集群没有keys这种方法,那么如何能快速准确地定位到这批key呢?

我们可以根据RedisCluster集群提供的getClusterNodes方法,获取到这个redis-cluster的每个节点,然后再去逐个遍历节点,获取节点的Jedis对像,使用单个jedis对像 再去获取前缀相同的keys

(2)获取到key集合之后,再遍历这些key,使用JedisClusterCRC16.getSlot(key)方法,定位到key所在的slot,把在同一个slot的key批量删除,这样做,第一能保证需要删的key都存在于redis集群,第二批量删除,提高效率。

具体代码:

Map<String, JedisPool> clusterNodes = jedis.getClusterNodes();
                String keysPattern =  keyPrefix + ":*";
                long countX = 0;
                long sTime = System.currentTimeMillis();
                for (Map.Entry<String, JedisPool> entry : clusterNodes.entrySet()) {  
                    Jedis jedisNode = entry.getValue().getResource();  
                    logger.info("redisip:{},port:{}" , jedisNode.getClient().getHost(), jedisNode.getClient().getPort());
                    if (!jedisNode.info("replication").contains("role:slave")) {  
                          Set<String> keys = jedisNode.keys(keysPattern);
                          logger.info("keys长度:{}" , keys.size());
                          Map<Integer, List<String>> map = new HashMap<>(6600);  
                          long countTmp = 0;
                            for (String key : keys) { int slot = JedisClusterCRC16.getSlot(key);
                                /**
                                 * cluster模式执行多key操作的时候,这些key必须在同一个slot上,
                                 * 不然会报:JedisDataException 
                                 */
                                //按slot将key分组,相同slot的key一起提交  
                                if (map.containsKey(slot)) {  
                                    map.get(slot).add(key);  
                                } else {  
                                     List<String> keyList = new ArrayList<String>();
                                     keyList.add(key);
                                     map.put(slot, keyList);  
                                    }
                                 
                            }
                            long count = 0;
                            for (Map.Entry<Integer, List<String>> integerListEntry : map.entrySet()) {  
                                count += jedisNode.del(integerListEntry.getValue().toArray(new String[integerListEntry.getValue().size()]));  
                                logger.info("删除:{}个",count);
                                countX++;
                            }  
                     }
                }
//                 logger.info("删除完成,共删除:{}个",countX);
                    logger.info("删除userid key任务结束,一共删除key数量:{},耗时:{}", countX , System.currentTimeMillis() - sTime);

redis集群(jedis)批量删除同一前缀

public Set<String> getByPrefix(String key) {
        Set<String> setResult = new HashSet<>();
        try {
            ShardedJedis jedis  = redisDataSource.getJedisClient();
            Iterator<Jedis> jedisIterator = jedis.getAllShards().iterator();
            while(jedisIterator.hasNext()){
                setResult = jedisIterator.next().keys(key+"*");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return setResult;
    }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • redis保存session信息的示例代码

    redis保存session信息的示例代码

    本文实现一个将session信息保存在 redis中,多个tomcat中的工程都从redis获取session信息的示例,本文给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-01-01
  • Redis高可用部署架构的实现

    Redis高可用部署架构的实现

    本文主要介绍了Redis高可用部署架构的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • Redis 的内存淘汰策略和过期删除策略的区别

    Redis 的内存淘汰策略和过期删除策略的区别

    这篇文章主要介绍了Redis 的内存淘汰策略和过期删除策略的区别,Redis 是可以对 key 设置过期时间的,因此需要有相应的机制将已过期的键值对删除,而做这个工作的就是过期键值删除策略
    2022-07-07
  • 浅谈一下Redis的数据结构

    浅谈一下Redis的数据结构

    这篇文章主要介绍了浅谈一下Redis的数据结构,简单字符串结构被用于存储redis的key对象和String类型的value对象,其中的free和len字段可以轻松的使得在该字符串被修改时判断是否需要扩容,需要的朋友可以参考下
    2023-08-08
  • redis并发之跳表的实现

    redis并发之跳表的实现

    跳表是一种用于实现有序集合的数据结构,本文主要介绍了redis并发之跳表的实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-05-05
  • redis通过lua脚本,获取满足key pattern的所有值方式

    redis通过lua脚本,获取满足key pattern的所有值方式

    这篇文章主要介绍了redis通过lua脚本,获取满足key pattern的所有值方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • Redis如何实现计数统计

    Redis如何实现计数统计

    这篇文章主要介绍了Redis如何实现计数统计方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Redis数据库分布式设计方案介绍

    Redis数据库分布式设计方案介绍

    大家好,本篇文章主要讲的是Redis数据库分布式设计方案介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • Redis RESP 协议实现实例详解

    Redis RESP 协议实现实例详解

    这篇文章主要为大家介绍了Redis RESP 协议实现实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • window手动操作清理redis缓存的技巧总结

    window手动操作清理redis缓存的技巧总结

    在本篇文章中小编给大家分享了关于window环境手动操作清理redis缓存的方法和技巧,有兴趣的朋友们可以跟着学习下。
    2019-07-07

最新评论