最近经常收到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);

最新文章

  1. C# 仿刷-框架MvcThrottle的使用
  2. C++之map、list操作
  3. WordPress的神器
  4. Matlab之cell使用
  5. C#中泛型容器Stack&lt;T&gt;
  6. Mac下安装Mysql出现 Can’t connect to local MySQL server through socket &#39;/tmp/mysql.sock&#39;
  7. [九度OJ]1113.二叉树(求完全二叉树任意结点所在子树的结点数)
  8. Eclipse中文乱码解决汇总(应该比较全):
  9. Java做acm所需要的基础知识之排序问题
  10. js判断获取浏览器关闭状态
  11. 蓝桥杯-格子中输出-java
  12. window(x64)+IIS+Access发布网站出现HTTP 错误 404.0 - Not Found
  13. 关于IE浏览器的一些思路
  14. Vue.js-05:第五章 - 计算属性与监听器
  15. mysql常用
  16. 家庭版Windows10没有远程桌面的问题
  17. AX_xSession
  18. OdnShop 发布 V1.0 正式版,完整可用的开源微商城系统
  19. 简述nginx(1)
  20. 洛谷P2055假期的宿舍

热门文章

  1. git stash应用
  2. ELK初学搭建
  3. js继承的几种方法和es6继承方法
  4. 01-HTML深入
  5. 【tp5.1】七牛云上传图片
  6. Learning Experience of Big Data:The First Day-Try to set up a network connection on my virtural machine
  7. linux文件操作篇 (四) 目录操作
  8. 文件 I/O字节流
  9. 004---Linux系统设置
  10. ffmpeg使用笔记