Elasticsearch

关于Elastic Search的5种分片查询

2019-01-12  本文已影响0人  秋慕云

分片查询方式

Es查询的时候,默认是随机从一些分片中查询数据,可以通过配置让es从某些分片中查询数据:

  1. _primary: 指查询只在主分片中查询

  2. _primary_first: 指查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。

  3. _local: 指查询操作会优先在本地节点有的分片中查询,没有的话再在其它节点查询。

  4. _only_node:指在指定id的节点里面进行查询,如果该节点只有要查询索引的部分分片,就只在这部分分片中查找,所以查询结果可能不完整。如_only_node:123在节点id为123的节点中查询。

  5. _prefer_node:nodeid 优先在指定的节点上执行查询

  6. Custom (string) value:用户自定义值,指在参数cluster.routing.allocation.awareness.attributes指定的值,如这个值设置为了zone,那么preference=zone的话就在awareness.attributes=zone*这样的节点搜索,如zone1、zone2。

7:_shards:0,1,2,3,4:查询指定分片的数据

使用过程中遇到的问题

虽然es提供了这几种分片查询方式,但如果想指定在某一个或多个节点中查询,比如node1和node2里面的分片能组成一个完整的索引,可以只在node1和node2中搜索就行了。用_only_node方式只能指定一个分区来进行查询,所以需要修改源码解决。

解决步骤如下:

首先,找到org.elasticsearch.cluster.routing.operation.plain.PlainOperationRouting这个类,es搜索时获取分片信息是通过这个类的。它的preferenceActiveShardIterator()方法就是根据条件来找出响应的分片。

看源码可知其主要是根据preference这个参数来决定取出的分片的。如果没有指定该参数,就随机抽取分片进行搜索。如果参数以_shards开头,则表示只查询指定的分片(注意,这个功能官网的文档中没有写到)。

其次,仿照单个节点分片查询(_only_node方式)的代码,追加实现多节点分片查询的功能,_only_node代码如下:

if (preference.startsWith("_only_node:")) {  
    return indexShard.onlyNodeActiveShardsIt(preference.substring("_only_node:".length()));  
}  

再其后面追加代码_only_nodes的多个分片实现,代码如下:

// 指定单个分片
if (preference.startsWith("_only_node:")) {  
    return indexShard.onlyNodeActiveShardsIt(preference.substring("_only_node:".length()));  
}  
// 指定多个分片
f (preference.startsWith("_only_nodes:"))  {  
    // 此处的onlyNodesActiveShardsIt方法在org.elasticsearch.cluster.routing.IndexShardRoutingTable中不存在,需要手动追加
    return indexShard.onlyNodesActiveShardsIt(preference.substring("_only_nodes:".length()));  
}  

上面的onlyNodesActiveShardsIt方法在org.elasticsearch.cluster.routing.IndexShardRoutingTable中不存在,需要手动追加,代码如下:

/** 
 * Prefers execution on the provided nodes if applicable. 
 */  
 public ShardIterator onlyNodesActiveShardsIt(String nodeIds) {  
     String[] ids = nodeIds.split(",");  
     ArrayList<ShardRouting> ordered = new ArrayList<ShardRouting>(shards.size());  
     // fill it in a randomized fashion  
     for (int i = 0; i < shards.size(); i++) {  
         ShardRouting shardRouting = shards.get(i);  
         for(String nodeId:ids){  
           if (nodeId.equals(shardRouting.currentNodeId())) {  
             ordered.add(shardRouting);  
           }  
         }  
     }  
     return new PlainShardIterator(shardId, ordered);  
 }  

最后,重新编译源码。查询时加上preference=_only_nodes:node1id,node2id 就可以指定在node1和node2中搜索

使用:
Elastic Search可以使用preference参数来指定分片查询的优先级,使用时就是在请求url上加上preference参数,如:client.prepareSearch(“index”).setPreference(“_primary”)

上一篇下一篇

猜你喜欢

热点阅读