java批量设置redis key的失效时间

之前因为redis中存在2E多条数据未设置失效时间,造成服务器内存一直在减小,查了下redis API也没有批量设置key失效时间的方法,所以就用java写了个小程序,性能还不错,因为刚接触这个水平有限,有能改进的地方希望大家指出,共同进步。
先简单的说下代码,我采用的方式是先导出redis中的所有key,然后把key切割成小文件(因为我导出后文件有几个G,所有切割成小文件,一个文件500w数据,主要看需求),然后把这些小文件存放到同一目录下,然后程序去读取目录下的小文件,根据小文件中的key设置失效时间并记录日志,因为我只是需要设置指定前缀key的失效时间,所以我加了个前缀的过滤,日志主要记录小文件名,这个小文件设置了多少个key。程序设置完一个小文件中的key后会删除这个小文件。

下面附上小程序代码


package redis.task;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Scanner;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
 * 读取指定目录下的所有文件中的key设置失效时间
 * @author Administrator
 *
 */
public class Task2 {
    // redis ip地址
    private static String redis_ip = "";
    // redis 端口号
    private static int redis_prot = 0;
    // redis keys文件夹路径
    private static String kyes_path = "";
    // 日志输出路径
    private static String log_path = "";
    // redis key前缀
    private static String key_prefix = "";
    // 失效时间(秒)
    private static int invalid_time = 0;
    
    private static JedisPool pool = null; 
    
    /**
     * 获取配置文件中的相关配置
     */
    static {
        // 获取配置文件路径
        String path = System.getProperty("user.dir");
        String file = path + "/config.properties";
        file = file.replaceAll("\\\\", "/");
        Properties pro = new Properties();
        try {
            pro.load(new  FileInputStream(new File(file)));
            redis_ip = pro.getProperty("redis_ip");
            redis_prot = Integer.parseInt(pro.getProperty("redis_prot"));
            kyes_path = pro.getProperty("keys_path").replaceAll("\\\\", "/");
            log_path = pro.getProperty("log_path").replaceAll("\\\\", "/");
            key_prefix = pro.getProperty("key_prefix");
            invalid_time = Integer.parseInt(pro.getProperty("invalid_time"));
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /**
     * 构建redis连接池
     * @return
     */
    public static JedisPool getPool() {
        if (pool == null) {  
            JedisPoolConfig config = new JedisPoolConfig();  
            //控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;  
            //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。  
            config.setMaxActive(500);  
            //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。  
            config.setMaxIdle(5);  
            //表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;  
            config.setMaxWait(1000 * 15);  
            //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;  
            config.setTestOnBorrow(true);  
            pool = new JedisPool(config, redis_ip, redis_prot);  
        }  
        return pool;  
    }
    
    /**
     * 返还到连接池
     * @param pool
     * @param redis
     */
    public static void returnResource(JedisPool pool, Jedis redis) {
        if (redis != null) {
            pool.returnResource(redis);
        }
    }
    
    /**
     * 设置key有效时间
     * @param key
     * @param seconds
     */
    public static void expire(String key, int seconds){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.expire(key, seconds);
        } catch (Exception e) {
            // 释放redis对象
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            // 返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    /**
     * 获取指定目录下的所有文件
     * @param resource
     * @return
     */
    public static File[] getFiles(String resource) {
        File file = new File(resource);
        return file.listFiles();
    }
    
    /**
     * 向指定文件中追加内容,若文件不存在则先创建文件
     * @param fileName
     * @param content
     */
    public static void appendFile(String fileName, String content) {
        FileWriter writer = null;
        try {
            // 若文件不存在,则先创建文件
            File file = new File(fileName);
            if (!file.exists())
                file.createNewFile();
            // 采用在文件尾部追加的方式写文件
            writer = new FileWriter(fileName, true);
            writer.write(content);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.flush();
                    writer.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    
    /**
     * 读取文件并设置失效时间,设置redis key 失效时间
     * @param filePath
     * @return key数量
     */
    public static int readFile(String filePath) {
        int sum = 0;
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath))));
            String key = "";
            while ((key = br.readLine()) != null) {
                if (key.startsWith(key_prefix)) {
                    System.out.println("io: " + key);
                    expire(key, invalid_time);
                    sum ++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return sum;
    }
    
    /**
     * 扫描方式读取文件,设置redis key 失效时间
     * @param filePath
     * @return key数量
     */
    public static int scannerReadFile(String filePath) {
        int sum = 0;
        FileInputStream inputStream = null;
        Scanner sc = null;
        try {
            inputStream = new FileInputStream(filePath);
            sc = new Scanner(inputStream, "UTF-8");
            while (sc.hasNext()) {
                String key = sc.nextLine();
                if (key.startsWith(key_prefix)) {
                    System.out.println("scanner: " + key);
                    expire(key, invalid_time);
                    sum ++;
                }
            }
            if (sc.ioException() != null) {
                throw sc.ioException();
            }
        } catch (IOException e){
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null)
                    inputStream.close();
                if (sc != null)
                    sc.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return sum;
    }
    
    /**
     * 迭代方式读取文件,设置redis key 失效时间
     * @param filePath
     * @return key数量
     * @throws Exception 
     */
    public static int lineIteratorReadFile (String filePath) {
        int sum = 0;
        LineIterator it = null;
        try {
            it = FileUtils.lineIterator(new File(filePath), "UTF-8");
            while (it.hasNext()) {
                String key = it.nextLine();
                if (key.startsWith(key_prefix)) {
                    System.out.println("iterator: " + key);
                    expire(key, invalid_time);
                    sum ++;
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return sum;
        } finally {
            LineIterator.closeQuietly(it);
        }
        return sum;
    }
    
    public static void main(String[] args) {
        int sum = 0;
        // 根据存放keys的文件夹路径获取文件夹下的所有key文件
        File[] files = getFiles(kyes_path);
        if (files != null) {
            for (File file : files) {
                String fileName = file.getName();
                String folderPath = kyes_path + fileName;
                try {
                    if (file.isFile()) {
                        appendFile(log_path, getTime(System.currentTimeMillis()) + " " + fileName + ":开始设置失效时间...\r\n");
                        // 1. 消耗内存最大
//                        sum = readFile(folderPath);
                        // 2. 消耗内存较小
//                        sum = scannerReadFile(folderPath);
                        // 3. 消耗内存最小
                        sum = lineIteratorReadFile(folderPath);
                        // 处理完文件后删除处理成功文件
                        file.delete();
                    }
                    
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    appendFile(log_path, getTime(System.currentTimeMillis()) + " " + fileName + ":设置失效时间完成,共设置 " + sum + " 个key\r\n\r\n");
                }
            }
        } else {
            System.out.println(kyes_path + "目录不存在或为空!");
        }
    }
    
    /**
     * 根据时间戳获取时间
     * @param time
     * @return
     */
    public static String getTime(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date(time));
    }
    
    /**
     * 获取项目路径
     * @return
     */
    public static String getPath() {
        return System.getProperty("user.dir");
    }
    
}

参数说明:

redis_ip:redis服务器ip地址
redis_prot:redis服务器端口号
keys_path:导出的redis key
log_path:程序日志输出的路径
key_prefix:需要设置key的前缀
invalid_time:失效时间(秒)

 

用到的jar

commons-io-2.2.jar

commons-pool-1.6.jar

jedis-2.2.0.jar

 

posted on 2016-01-12 13:03  废材不良  阅读(5406)  评论(0编辑  收藏  举报

导航