在开发过程中,经常会遇到Redis的机器内存过高而导致其他服务受到影响,主要原因是没有对一些临时的key设置过期时间或者定期清理,时间一长就会造成很多垃圾数据塞满内存,那么此时就可以通过keys命令将匹配到的key删除。
单节点Redis删除key
单节点不存在槽(slot)
的概念,所以可以直接使用如下命令进行删除
redis-cli keys "*gitlab*"|xargs redis-cli del
上面的命令表示删除所有包含gitlab
的key,使用keys *gitlab*
将会得到如下结果:
root@ubuntu:~# redis-cli -n 0 keys "*gitlab*" 1) "resque:gitlab:cron_job:expire_build_artifacts_worker" 2) "resque:gitlab:cron_job:admin_email_worker:enqueued" 3) "resque:gitlab:stat:failed:2019-07-07" 4) "resque:gitlab:stat:failed" 5) "resque:gitlab:cron_job:repository_check_worker" 6) "resque:gitlab:cron_jobs" 7) "resque:gitlab:stat:processed:2019-07-07" 8) "resque:gitlab:stat:failed:2019-07-07" 9) "resque:gitlab:cron_job:stuck_ci_builds_worker:enqueued" 10) "resque:gitlab:cron_job:repository_archive_cache_worker" 11) "resque:gitlab:cron_job:stuck_ci_builds_worker" 12) "resque:gitlab:processes"
那么这些key将会被删除。
当然,有些时候还会有分库的场景,单节点的Redis默认有16
个数据库,那么还可以指定数据库来进行匹配删除,使用-n 数据库编号
即可,例如,删除数据库2
中的所有*gitlab*
的key:
redis-cli -n 2 keys "*gitlab*"| xargs redis-cli -n 2 del
Redis Cluster模式删除key
如果Redis是集群的模式,那么此时数据库只能是0
,并且不能使用keys
命令和管道
的组合来匹配删除了,因为数据分布在不同的节点的内存槽里面,需要针对每个节点的key进行删除,此时我们需要借助代码来实现。
package cn.net.dev.study; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.junit.Test; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * @author dev * @version 1.0 * date 2019-07-17 14:00 */ public class TestRedisCluster { @Test public void testRedis() { Set hostAndPortsSet = new HashSet<>(); // 添加节点 三主三从 hostAndPortsSet.add(new HostAndPort("10.10.170.161", 7000)); hostAndPortsSet.add(new HostAndPort("10.10.170.161", 7001)); hostAndPortsSet.add(new HostAndPort("10.10.170.161", 7002)); hostAndPortsSet.add(new HostAndPort("10.10.170.161", 7003)); hostAndPortsSet.add(new HostAndPort("10.10.170.161", 7004)); hostAndPortsSet.add(new HostAndPort("10.10.170.161", 7005)); // Jedis连接池配置 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxIdle(10); jedisPoolConfig.setMaxTotal(30); jedisPoolConfig.setMinIdle(0); jedisPoolConfig.setMaxWaitMillis(200000); // 设置200秒 jedisPoolConfig.setTestOnBorrow(true); JedisCluster jedisCluster = new JedisCluster(hostAndPortsSet, jedisPoolConfig); Map<String, JedisPool> clusterNodes = jedisCluster.getClusterNodes(); for (JedisPool pool : clusterNodes.values()) { Jedis jedis = pool.getResource(); Set keySet = jedis.keys("*gitlab*"); for (String key : keySet) { System.out.println(key); if (!key.equals("")) { jedisCluster.del(key); } } } } }
此时就会将每个节点保存的Key进行删除,不过速度比较慢,而且如果在redis的MaxWaitMillis
没有删除完key,会出现保存。如果数据量较大,可以将MaxWaitMillis
设置大一点,目前本程序中设置的200000
毫秒,总共调用了3次,删除了20G的数据。代码中有个判断空的逻辑,我也不清楚为啥读出来有些key是""
,所以就特殊处理了一下。