服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Redis - redis集群实现清理前缀相同的key

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

2021-11-19 17:39浮白斋主人 Redis

这篇文章主要介绍了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集群,第二批量删除,提高效率。

具体代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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)批量删除同一前缀

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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;
    }

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

原文链接:https://www.cnblogs.com/fubaizhaizhuren/p/8405836.html

延伸 · 阅读

精彩推荐
  • RedisRedis 事务知识点相关总结

    Redis 事务知识点相关总结

    这篇文章主要介绍了Redis 事务相关总结,帮助大家更好的理解和学习使用Redis,感兴趣的朋友可以了解下...

    AsiaYe8232021-07-28
  • RedisRedis如何实现数据库读写分离详解

    Redis如何实现数据库读写分离详解

    Redis的主从架构,能帮助我们实现读多,写少的情况,下面这篇文章主要给大家介绍了关于Redis如何实现数据库读写分离的相关资料,文中通过示例代码介绍...

    罗兵漂流记6092019-11-11
  • RedisRedis的配置、启动、操作和关闭方法

    Redis的配置、启动、操作和关闭方法

    今天小编就为大家分享一篇Redis的配置、启动、操作和关闭方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    大道化简5312019-11-14
  • Redisredis 交集、并集、差集的具体使用

    redis 交集、并集、差集的具体使用

    这篇文章主要介绍了redis 交集、并集、差集的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友...

    xiaojin21cen10152021-07-27
  • Redisredis中如何使用lua脚本让你的灵活性提高5个逼格详解

    redis中如何使用lua脚本让你的灵活性提高5个逼格详解

    这篇文章主要给大家介绍了关于redis中如何使用lua脚本让你的灵活性提高5个逼格的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具...

    一线码农5812019-11-18
  • Redis详解Redis复制原理

    详解Redis复制原理

    与大多数db一样,Redis也提供了复制机制,以满足故障恢复和负载均衡等需求。复制也是Redis高可用的基础,哨兵和集群都是建立在复制基础上实现高可用的...

    李留广10222021-08-09
  • Redisredis实现排行榜功能

    redis实现排行榜功能

    排行榜在很多地方都能使用到,redis的zset可以很方便地用来实现排行榜功能,本文就来简单的介绍一下如何使用,具有一定的参考价值,感兴趣的小伙伴们...

    乘月归5022021-08-05
  • RedisRedis全量复制与部分复制示例详解

    Redis全量复制与部分复制示例详解

    这篇文章主要给大家介绍了关于Redis全量复制与部分复制的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis爬虫具有一定的参考学习...

    豆子先生5052019-11-27