ElasticSearch数据迁移之reindex

需要的jar包,我这里使用maven的pom.xml导入,可以自己下载jar包并导入到项目中

        	
			com.alibaba
			fastjson
			1.2.24
		
		
		
			org.apache.logging.log4j
			log4j-core
			2.10.0
		
		
			junit
			junit
			4.2
			test
		
		
		
			org.apache.httpcomponents
			httpclient
			4.5.2
		
		
			org.elasticsearch.client
			transport
			5.4.2
		
		
			org.elasticsearch
			elasticsearch
			5.4.2
		

连接集群ClientConnect.java

package util;

import java.net.InetSocketAddress;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

/**
 * 
 * @createDate 2018年3月8日
 * @class_name ClientConnect 连接ES集群
 * @description : 建立es的client,通过getClient()调用,只能连接es5.4.2
 */
public class ClientConnect {
	private TransportClient client;

	public TransportClient getClient() {
		return client;
	}

	/**
	 * 
	 * @param clusterName            集群名称
	 * @param clusterAddress         集群ip地址
	 * @param port                   端口号
	 */
	@SuppressWarnings({ "unchecked", "resource" })
	public ClientConnect(String clusterName, String clusterAddress, int port) {
		Settings settings = Settings.builder().put("cluster.name", clusterName)
				.build();
		client = new PreBuiltTransportClient(settings)
				.addTransportAddress(new InetSocketTransportAddress(
						new InetSocketAddress(clusterAddress, port)));
		System.out.println("success connect");
	}

}

mapping结构获取与构建Mapping.java

package util;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSONObject;

/**
 * 
 * @createDate 2018年3月22日
 * @className Mapping
 * @description : 获取和创建es服务器上的mapping
 * @lastUpdate_time 2018年3月22日
 */
public class Mapping {
	private static final Mapping mapping=new Mapping();
	private Mapping(){}
	public static Mapping getInstance(){
		return mapping;
	}
	
	/**
	 * 
	 * @description : 建立索引及其mapping
	 * @param index    索引名称
	 * @param json     json格式的参数
	 * @return String es的json格式回复
	 * @throws Exception
	 */
	public String setMapping(String url,String index, String json) throws Exception {
		// 构建网址实例
		String reindexUri = url +"/"+ index;
		URI uri = new URI(reindexUri);
		// 建立连接客户端
		HttpClient client = HttpClients.createDefault();
		// 设置PUT请求的网址
		HttpPut httpput = new HttpPut(uri);
		// 设置允许添加json格式参数
		httpput.addHeader(HTTP.CONTENT_TYPE, "application/json");
		// 转化成请求格式
		StringEntity se = new StringEntity(json);
		// 添加参数
		httpput.setEntity(se);
		// 客户端发送请求,并获取回复
		HttpResponse response = client.execute(httpput);
		// 将回复转成JSON字符串
		String responseJSON = EntityUtils.toString(response.getEntity());

		return responseJSON;
	}

	/**
	 *
	 * @throws Exception
	 * @description : 获取指定索引的mapping
	 * @param url 服务器ip	
	 * @param index	索引	
	 * @param type	类型
	 * @return String es的json格式回复
	 * @throws Exception
	 */
	public String getMapping(String url,String index,String type) throws Exception {
		
		// 构建网址实例
		String reindexUri = url +"/"+ index
				+ "/_mapping/" + type;
		URI uri = new URI(reindexUri);
		// 建立连接客户端
		HttpClient client = HttpClients.createDefault();
		// 设置GET请求的网址
		HttpGet httpget = new HttpGet(uri);
		// 客户端发送请求,并获取回复
		HttpResponse response = client.execute(httpget);
		// 将回复转成JSON字符串
		String responseJSON = EntityUtils.toString(response.getEntity());
		return responseJSON;
	}
	
	/**
	 * 
	 * @description : 构建mapping,需根据自己需求填写
	 * @return	json的mapping参数
	 */
	public JSONObject mapJsonBulid() {
		// TODO Auto-generated method stub
		JSONObject json = new JSONObject();
		json.put("type", "keyword");
		JSONObject json2 = new JSONObject();
		json2.put("name", json);
		JSONObject json3 = new JSONObject();
		json3.put("type", "keyword");
		json2.put("uuid", json3);
		JSONObject json5 = new JSONObject();
		json5.put("properties", json2);
		JSONObject json6 = new JSONObject();
		json6.put("current_user", json5);
		JSONObject json7 = new JSONObject();
		json7.put("mappings", json6);
		System.out.println("createJson3" + json7.toJSONString());
		return json7;
		// {"mappings": {
		// "current_user": {
		// "properties": {
		// "name": {"type": "keyword"},
		// "unid": {"type": "keyword"}
		// }}}}
	}
}

reindex请求发送HttpRequest.java
package util;
import java.net.URI;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

	/**
	 * 
	 * @createDate 2018年3月22日
	 * @className HttpRequest
	 * @description : 向es服务器发送请求
	 * @lastUpdateTime 2018年3月22日
	 */
public class HttpRequest {

	private static final HttpRequest httpRequest = new HttpRequest();

	private HttpRequest() {
	}

	public static HttpRequest getInstance() {
		return httpRequest;
	}

	/**
	 * 
	 * @description : 发送reindex请求,
	 * @param url     服务器ip地址
	 * @param json    发送的json格式参数
	 * @return String 服务器返回的json格式回复
	 * @throws Exception
	 */
	public String reindex(String url, String json) throws Exception {
		HttpClient client = HttpClients.createDefault();
		URI uri = new URI(url + "/_reindex");
		HttpPost httppost = new HttpPost(uri);
		httppost.addHeader(HTTP.CONTENT_TYPE, "application/json");
		StringEntity se = new StringEntity(json);
		httppost.setEntity(se);
		HttpResponse response = client.execute(httppost);
		return EntityUtils.toString(response.getEntity());
	}

}

构建reindex的参数ReindexJSONBuild.java

package util;

import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;

import com.alibaba.fastjson.JSONObject;

	/**
	 * 
	 * @createDate 2018年3月22日
	 * @className ReindexJSONBuild
	 * @description : 构建reindex的json格式参数
	 * @lastUpdateTime 2018年3月22日
	 */
public class ReindexJSONBuild {
	private static final ReindexJSONBuild reindexJSONBuild=new ReindexJSONBuild();
	private ReindexJSONBuild(){}
	public static ReindexJSONBuild getInstance(){
		return reindexJSONBuild;
	}
	
	/**
	 * 	
	 * @description : 构建reindex的json格式请求
	 * @param urlRemote 	远程服务器地址
	 * @param sourceIndex	迁移前index
	 * @param sourceType	迁移前type	
	 * @param destIndex		迁移后index
	 * @return	String json格式的reindex请求
	 */
	public String reindexJson1(String urlRemote,String sourceIndex,String sourceType,String destIndex) {
		// 创建json对象, 其中一个创建json的方式
		JSONObject json = new JSONObject();
		json.put("host", urlRemote);
		JSONObject json2 = new JSONObject();
		json2.put("remote", json);
		json2.put("index", sourceIndex);
		json2.put("type", sourceType);
		JSONObject json3 = new JSONObject();
		json3.put("index", destIndex);
		JSONObject json4 = new JSONObject();
		json4.put("source", json2);
		json4.put("dest", json3);
	//	System.out.println("reindexJson1:" + json4.toJSONString());
		return json4.toJSONString();
	}

	/**
	 * 	
	 * @description : 构建reindex的json格式请求
	 * @param urlRemote 	远程服务器地址
	 * @param sourceIndex	迁移前index
	 * @param sourceType	迁移前type	
	 * @param destIndex		迁移后index
	 * @return	String json格式的reindex请求
	 */
	public String reindexJson2(String urlRemote,String sourceIndex,String sourceType,String destIndex) throws Exception {
		// 创建json对象, 其中一个创建json的方式
		XContentBuilder source = XContentFactory.jsonBuilder()
				.startObject()
					.startObject("source")
						.startObject("remote")
						.field("host", urlRemote)
						.endObject()
						.field("index", sourceIndex)
						.field("type",sourceType)
					.endObject()
					.startObject("dest")
						.field("index", destIndex)
					.endObject()
				.endObject();
		//System.out.println("createJson4");
		return source.string();
	}
	
}

ElasticSearch集群中的index获取IndexAndTypeBuild.java

package util;


import java.util.ArrayList;
import java.util.List

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;

/**
 * 
 * @createDate 2018年3月22日
 * @className IndexAndTypeBuild
 * @description : 从es服务器上获取所有的索引和类型
 * @lastUpdateTime 2018年3月22日
 */
public class IndexAndTypeBuild {
	private static final IndexAndTypeBuild indexAndTypeBuild = new IndexAndTypeBuild();

	private IndexAndTypeBuild() {
	}

	public static IndexAndTypeBuild getInstance() {
		return indexAndTypeBuild;
	}

	/**
	 * 
	 * @description : 建立index-type信息
	 * @param client      客户端
	 * @return index-type的所有信息
	 * @throws Exception
	 */
	public List getIndexAndType(TransportClient client)
			throws Exception {
		// 某一个index下的type数
		int typeCount;
		// 某一个index下的所有type
		String[] types;
		// 一对index-type,用于生成一条记录
		String[] indexType = new String[] {};
		// 所有的index-type数据
		List indexTypeList = new ArrayList();

		// 用户端从服务器上获取所有index
		ImmutableOpenMap indexMap = client.admin()
				.cluster().prepareState().execute().actionGet().getState()
				.getMetaData().getIndices();
		// 将获取的index转化成数组
		Object[] indexs = indexMap.keys().toArray();

		// 对每一个index进行处理
		int size = indexMap.size();
		for (int i = 0; i < size; i++) {
			// 获取当前index下有多少个type
			typeCount = indexMap.get(indexs[i].toString()).getMappings().size();

			if (typeCount == 1) {
				// 获取type,先用split切割掉后面的无用部分,然后去掉最前面的“[”
				types = indexMap.get(indexs[i].toString()).getMappings()
						.toString().split("=");
				types[0] = types[0].substring(1);
				// 生成一条index-type记录,添加进去
				indexType = new String[] { indexs[i].toString(), types[0] };
				indexTypeList.add(indexType);

			} else if (typeCount > 1) {
				// 获取type,先用split将type分割开,继续用split切割掉每个type后面的无用部分,然后去掉最前面的“[”
				types = indexMap.get(indexs[i].toString()).getMappings()
						.toString().split(",");
				for (String type : types) {
					type = type.split("=")[0].substring(1);
					// 第三个参数作为判定是否index有多个type,生成一条index-type记录,添加进去
					indexType = new String[] { indexs[i].toString(), type,
							"multiType" };
					indexTypeList.add(indexType);
				}
			} else {
				System.out.println(indexs[i].toString() + "下没有type");
			}
		}
		// for (int i = 0; i < indexTypeList.size(); i++) {
		// System.out.print("index:"+indexTypeList.get(i)[0] + ",  type:");
		// System.out.println(indexTypeList.get(i)[1]);
		// }
		return indexTypeList;
	}

}

运用上面的类迁移数据ReindexTest.java

package instancetest;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.Properties;

import org.elasticsearch.client.transport.TransportClient;

import util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * 
 * @createDate 2018年3月21日
 * @className ReindexTest
 * @description : reindex测试
 * @lastUpdateTime 2018年3月23日
 */
public class ReindexTest {

	public static void main(String[] args) throws Exception {
		// 建立工具类实例
		Mapping mapping = Mapping.getInstance();
		HttpRequest httpRequest = HttpRequest.getInstance();
		ReindexJSONBuild reindexJSONBuild = ReindexJSONBuild.getInstance();
		IndexAndTypeBuild indexAndTypeBuild = IndexAndTypeBuild.getInstance();
		TransportClient client = new ClientConnect("elasticsearch","192.168.203.201", 9320).getClient();

		// 获取已创建过的index和type
		URL in = mapping.getClass().getResource("/indexType.properties");
		InputStream inin = in.openStream();
		Properties prop = new Properties();
		prop.load(inin);

		String index;
		String destIndex;
		String type;
		boolean isNotMulit;
		String response;
		String remoteurl = "http://192.168.203.201:9220";
		String buildurl = "http://192.168.203.201:9200";

		// 获取服务器上所有的index和type
		List indexTypeList = indexAndTypeBuild.getIndexAndType(client);

		for (String[] indexType : indexTypeList) {
			index = indexType[0];
			type = indexType[1];
			isNotMulit = indexType.length == 2;
			// 获取mapping
			JSONObject tempjson = JSON.parseObject(mapping.getMapping(remoteurl, index, type));
			// 判断该index是否有多个type
			if (isNotMulit) {
				// 判断是否创建过该index
				if (null == prop.get(index)) {
					// 先建立mapping
					response = mapping.setMapping(
							buildurl, 
							index, 
							tempjson
							.getJSONObject(index)
							.toJSONString());
					// 判断是否建立成功
					if (response.substring(2, 7).equals("ackno")) {
						// 将index和type输入到配置文件中
						prop.setProperty(index, type);
						FileOutputStream fos = new FileOutputStream(
								mapping
								.getClass()
								.getResource("/indexType.properties")
								.getPath());
						prop.store(fos, null);
						fos.flush();
						fos.close();
					}
					// 构建reindex请求的json格式
					String json = reindexJSONBuild.reindexJson1(remoteurl, index, type, index);
					// 发送请求,并打印回复
					System.out.println(httpRequest.reindex(buildurl, json));
				} else {
					System.out.println("已创建过" + index);
				}
			} else {
				destIndex = index + "_" + type;
				// 判断是否创建过该index
				if (null == prop.get(destIndex)) {
					// 先建立mapping
					response = mapping.setMapping(
							buildurl, 
							destIndex, 
							tempjson
							.getJSONObject(index)
							.toJSONString());
					// 判断是否建立成功
					if (response.substring(2, 7).equals("ackno")) {
						// 将index和type输入到配置文件中
						prop.setProperty(destIndex, type);
						FileOutputStream fos = new FileOutputStream(
								mapping
								.getClass()
								.getResource("/indexType.properties")
								.getPath());
						prop.store(fos, null);
						fos.flush();
						fos.close();
					}
					// 构建reindex请求的json格式
					String json = reindexJSONBuild.reindexJson1(remoteurl, index, type, destIndex);
					// 发送请求,并打印回复
					System.out.println(httpRequest.reindex(buildurl, json));
				} else {
					System.out.println("已创建过" + destIndex);
				}
			}
		}
	}
}

注意:迁移前需在elasticsearch.yaml文件中添加下面配置

reindex.remote.whitelist: host:port

此程序为当初将ElasticSearch版本为5.4.2的集群迁移到ElasticSearch版本为6.0.0的集群上编写的。

因为使用了ambari安装的ElasticSearch,所以ElasticSearch的结构不同,且版本不同,有一些地方出现变化,无法直接用新版本覆盖升级。

故用以上程序保证数据完整地迁移到新集群。


你可能感兴趣的:(elasticsearch)