念念不忘
必有回响

删除Redis中keys命令匹配到所有key

在开发过程中,经常会遇到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进行删除,此时我们需要借助代码来实现。

使用Jedis实现:

package xyz.cco.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 Cco.Xyz
 * @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是"",所以就特殊处理了一下。

使用Lettuce实现:

Set keys = redisLettuceTemplate.keys(prefix);
if (Optional.ofNullable(keys).isPresent()){
    keys.forEach(e -> {
        redisLettuceTemplate.delete(e);
    });
}

 

赞(0) 打赏
未经允许不得转载:码农志 » 删除Redis中keys命令匹配到所有key

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏