本程序主要使用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>