Java解析Redis rdb文件

        本程序主要使用java解析redis持久化rdb文件,考虑到rdb文件可能比较大,解析时间比较长,所以采用一个线程解析,一个线程写入目标文件的方式进行。

以下对每个类进行讲解:

1、Common类主要用于定义rdb文件目录及目标文件目录

package redis.java_redis_rdb;

import java.io.File;

public class Common {
    public static String RDBPATH = "C:"+File.separator
           +"运维"+File.separator+"rdb文件导出"+File.separator+"dump1.rdb";

    public static String TXTPATH = "C:"+File.separator+"javaRedisRdb10.txt";

}

2、LinkenQueue类主要将解析的数据放入队列,并依次读取写入文件

package redis.java_redis_rdb;

import java.util.concurrent.LinkedBlockingQueue;

public class LinkenQueue {
    private static LinkedBlockingQueue<RedisRdbParse> linkedBlockingQueue;

    static {
        linkedBlockingQueue = new LinkedBlockingQueue<>();
    }

    public static LinkedBlockingQueue<RedisRdbParse> getLinkedBlockingQueue(){
        return linkedBlockingQueue;
    }

}

3、定义解析的对象类  包括key值、value值及数据类型

package redis.java_redis_rdb;

public class RedisRdbParse {
    private String key;
    private String value;
    private String type;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

4、ParseRdb 用于解析RDB文件

package redis.java_redis_rdb;

import net.whitbeck.rdbparser.*;

import java.io.File;
import java.io.IOException;

public class ParseRdb implements Runnable{
    File file;

    /**
     * 判断rdb文件是否存在
     * @param f
     */
    public ParseRdb(File f){
        this.file = f;
        if(file.exists()){
            System.out.println("exists");
        }else{
            System.out.println("not exists");
        }
    }
    @Override
    public void run() {
        try{
            RdbParser parser = new RdbParser(file);
            Entry e;
            int i = 1;
            while ((e = parser.readNext()) != null) {
                //System.out.println("NO:" + i);
                switch (e.getType()) {
                    case SELECT_DB:
                        System.out.println("Processing DB: " + ((SelectDb)e).getId());
                        System.out.println("--------------------------------------------");
                        break;
                    case EOF:
                        System.out.print("End of file. Checksum: ");
                        for (byte b : ((Eof)e).getChecksum()) {
                            System.out.print(String.format("%02x", b & 0xff));
                        }
                        System.out.println("--------------------------------------------");
                        break;
                    case KEY_VALUE_PAIR:
                        RedisRdbParse rrp = new RedisRdbParse();
                        KeyValuePair kvp = (KeyValuePair)e;
                        rrp.setKey(new String(kvp.getKey(), "ASCII"));
                        String value="";
                        for (byte[] val : kvp.getValues()) {
                            value = value + new String(val, "ASCII") + " ";
                        }
                        System.out.println(new String(kvp.getKey())+"------------"
                                +kvp.getType()+"----------"+value);

                        rrp.setType(String.valueOf(kvp.getValueType()));
                        LinkenQueue.getLinkedBlockingQueue().add(rrp);
                        break;
                }
                i++;
            }
            RedisRdbParse rrpEnd = new RedisRdbParse();
            rrpEnd.setKey("END---");//该key用于完成判断,停止程序用
            LinkenQueue.getLinkedBlockingQueue().add(rrpEnd);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

5、SaveRedisObject 将解析后的数据进行保存

package redis.java_redis_rdb;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class SaveRedisObject implements Runnable{
    private File file;
    public SaveRedisObject(File f){
        this.file = f;
    }

    /**
     * 当前只存入了key,若需要其他信息可以从redisRdbParse对象中直接get
     */
    @Override
    public void run() {
        //判断文件是否存在,若存在先删除,再创建新的
        if(parseFile()){
            try {
                BufferedWriter out = new BufferedWriter(new FileWriter(file));
                int i=0;
                while(true){
                    System.out.println(LinkenQueue.getLinkedBlockingQueue().size());
                    if(LinkenQueue.getLinkedBlockingQueue().size()>0){
                        RedisRdbParse redisRdbParse = LinkenQueue.getLinkedBlockingQueue().take();
                        System.out.println(redisRdbParse.getKey());
                        out.write(redisRdbParse.getType() + "              " + redisRdbParse.getKey() +"\r\n");

                        if(redisRdbParse.getKey().equals("END---")){
                            System.out.println("The file is end ------------");
                            break;
                        }
                    }
                }
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 判断文件是否存在,若存在先删除
     * @return
     */
    public boolean parseFile(){
        if(file.exists()){
            file.delete();
        }
        try {
            file.createNewFile();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}

7、Main 执行

package redis.java_redis_rdb;

import java.io.File;

public class Main {
    public static void main(String[] args) throws Exception {
        File rdbFile = new File(Common.RDBPATH);
        File txtFile = new File(Common.TXTPATH);
        ParseRdb parseRdb = new ParseRdb(rdbFile);
        SaveRedisObject sroj = new SaveRedisObject(txtFile);
        new Thread(parseRdb).start();
        new Thread(sroj).start();
    }

}

8、pom文件关键引用

        <dependency>
            <groupId>net.whitbeck</groupId>
            <artifactId>rdb-parser</artifactId>
            <version>2.0.0</version>
        </dependency>

猜你喜欢

转载自blog.csdn.net/zhangmuqiang/article/details/131662829