ES提供几种客户端供使用,引入不同的maven依赖即可
transport在ES7.0之后将会逐步去除
当ES的版本是6.0.0以上时,其建议我们使用官方的Java High-Level Rest Client
保证入数据的数据均衡性。
使用Java API时,当设置client.transport.sniff为true(默认为false) 时,列表为所有数据节点,否则节点列表为构建客户端对象时传入的节 点列表。
使用REST API时,列表为构建对象时添加进去的节点。 为了节点间的任务尽量均衡,数据写入客户端应该把bulk请求轮询 发送到各个节点。 当使用Java API或REST API的bulk接口发送数据时,客户端将会轮 询发送到集群节点,节点列表取决于:
使用Java API时,当设置client.transport.sniff为true(默认为false) 时,列表为所有数据节点,否则节点列表为构建客户端对象时传入的节 点列表。
使用REST API时,列表为构建对象时添加进去的节点。
org.elasticsearch.client
elasticsearch-rest-high-level-client
${es.client.version}
注意关闭连接
private static RestHighLevelClient client;
private static void init() {
client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("192.168.2.101", 9200, "http"),
new HttpHost("192.168.2.102", 9201, "http"),
new HttpHost("192.168.2.103", 9201, "http")
));
}
1:写入数据到索引中,索引的mapping提前设置完毕
private static void index() {
//构建索引请求
IndexRequest indexRequest = new IndexRequest("test_field", "type1","5");
//此处采用map进行构建
HashMap hashMap = new HashMap<>();
hashMap.put("name", "lisan");
hashMap.put("age",5);
indexRequest.source(hashMap);
//执行请求
try {
//得到请求返回情况
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
String id = indexResponse.getId();
System.out.println("id:"+id );
} catch (IOException e) {
e.printStackTrace();
}
}
2:第二种查询方式
private static void queryData(RestClient restClient) throws Exception {
Map params = Collections.singletonMap("pretty", "true");
Response rsp = null;
try {
rsp = restClient.performRequest("GET", "/" + index+ "/" + type+ "/" + id,params);//performRequest可以构建各种请求进行执行
Assert.assertEquals(rsp.getStatusLine().getStatusCode(), HttpStatus.SC_OK);
LOG.info("queryData,response entity is : " + EntityUtils.toString(rsp.getEntity()));
} catch (Exception e) {
Assert.fail();
}
}
查看写入结果:查看命令
GET test_field/type1/_search
{
"query":{
"bool": {
"must":[
{"match":{"name": "lisan"}},
{ "match":{"age":5}}
]
}
}
}
结果:可知写入成功。
"hits" : [
{
"_index" : "test_field",
"_type" : "type1",
"_id" : "5",
"_score" : 2.2039728,
"_source" : {
"name" : "lisan",
"age" : 5
}
}
]
使用api进行查询,太大的数据量一般建议使用Scroll
private static void get(){
GetRequest getRequest = new GetRequest("test_field", "type1","5");
try {
GetResponse documentFields = client.get(getRequest, RequestOptions.DEFAULT);
String id = documentFields.getId();
Map source = documentFields.getSource();
Object name1 = source.get("name");
System.out.println(id+" name:"+name1);
} catch (IOException e) {
e.printStackTrace();
}
}
项目一般使用此api进行数据的写入操作
bulk优化
1:使用bulk命令进行批量索引数据时,每批次提交的数据大小为5~15MB。比如每条数据大小为1k,那么建议批量提交的数据条数为5000条。
当前集群的最佳批量请求大小,可以从5MB开始测试,缓慢增加这个大小,直到写入性能不能提升为止。
2:每个批量请求中只处理一个索引的数据,一个bulk请求只写入一个索引的数据,不建议一个bulk请求同时写入多个索引的数据,不同索引的数据分多个bulk请求提交。
1:概念
bulk批量请求可用于使用单个请求执行多个(create、index、update、delete)操作
index(最常用) : 如果文档不存在就创建他,如果文档存在就更新他
create : 如果文档不存在就创建他,但如果文档存在就返回错误
使用时一定要在metadata设置_id值,他才能去判断这个文档是否存在
update : 更新一个文档,如果文档不存在就返回错误
使用时也要给_id值,且后面文档的格式和其他人不一样
delete : 删除一个文档,如果要删除的文档id不存在,就返回错误
BulkResponse的api:
2:批量代码:用source构建数据
private static void bulk(){
//1:构建bulk批量操作
BulkRequest bulkRequest = new BulkRequest();
//2:通过add操作实现一个请求执行多个操作
//source构建数据时,k,v,k,v形式。索引-类型-文档id.source(数据)
bulkRequest.add(new IndexRequest("test_field", "type1","6").source("name","lisi","age",5));
//3:同步执行操作:可通过for等循环控制,实现一次导入多条数据:
try {
BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
RestStatus status = bulk.status();
System.out.println(status);
} catch (IOException e) {
e.printStackTrace();
}
}
查看批量导入结果:成功
{
"_index" : "test_field",
"_type" : "type1",
"_id" : "6",
"_score" : 1.0,
"_source" : {
"name" : "lisi",
"age" : 5
}
}
2.1:BulkResponse 的api
1:检查批量响应的执行状态
if (bulk.hasFailures()){//返回true,至少一个失败,进行迭代处理
for (BulkItemResponse itemResponse : bulk) {
BulkItemResponse.Failure failure = itemResponse.getFailure();
}
}
3:第二种批量导入:使用XContentBuilder创建json数据+异步提交
项目中使用此方法的较多,利于schema的管理
private static void bulk() {
//1:构建bulk批量操作
BulkRequest bulkRequest = new BulkRequest();
//2:通过add操作实现一个请求执行多个操作
// bulkRequest.add(new IndexRequest("test_field", "type1","6").source("name","lisi","age",5));
try {
//:3:使用XContentBuilder创建json数据
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
//开始
xContentBuilder.startObject();
//项目中一般通过schema进行fields的加载获取,再进行XContentBuilder 的构建
xContentBuilder.field("name", "wangwu");
xContentBuilder.field("age", 8);
//构建结束,
xContentBuilder.endObject();
bulkRequest.add(new IndexRequest("test_field", "type1", "7").source(xContentBuilder));
} catch (IOException e) {
e.printStackTrace();
}
//4:执行操作
try {
//同步执行
BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
//异步执行
ActionListener actionListener = new ActionListener() {
@Override
public void onResponse(BulkResponse bulkItemResponses) {
/*当执行成功完成时调用。该响应作为参数提供,并包含执行的每个操作的单个结果的列表。请注意,一个或多个操作可能已失败,而其他操作已成功执行*/
for (BulkItemResponse bulkItemResponse : bulkItemResponses) {
DocWriteResponse itemResponse = bulkItemResponse.getResponse();
if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX
|| bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
IndexResponse indexResponse = (IndexResponse) itemResponse;
} else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
UpdateResponse updateResponse = (UpdateResponse) itemResponse;
} else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
}
}
}
@Override
public void onFailure(Exception e) {
/*批量失败时*/
}
};
client.bulkAsync(bulkRequest, RequestOptions.DEFAULT, actionListener);
RestStatus status = bulk.status();
System.out.println(status);
} catch (IOException e) {
e.printStackTrace();
}
}
查看结果:成功
{
"_index" : "test_field",
"_type" : "type1",
"_id" : "7",
"_score" : 1.0,
"_source" : {
"name" : "wangwu",
"age" : 8
}
}
关闭客户端连接
private static void close() {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
服务器台38台,cores=38*4
数据量1000w/min ,时间5min左右
参考文献:es官方开发文档