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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM