elasticsearch的5種分片查詢優先級


elasticsearch可以使用preference參數來指定分片查詢的優先級,使用時就是在請求url上加上preference參數,如:http://ip:host/index/_search?preference=_primary 
java的調用接口翻譯為:client.prepareSearch(“index”).setPreference(“_primary”)。 
默認情況下es有5種查詢優先級: 
_primary: 指查詢只在主分片中查詢 
_primary_first: 指查詢會先在主分片中查詢,如果主分片找不到(掛了),就會在副本中查詢。 
_local: 指查詢操作會優先在本地節點有的分片中查詢,沒有的話再在其它節點查詢。 
_only_node:指在指定id的節點里面進行查詢,如果該節點只有要查詢索引的部分分片,就只在這部分分片中查找,所以查詢結果可能不完整。如_only_node:123在節點id為123的節點中查詢。 
Custom (string) value:用戶自定義值,指在參數cluster.routing.allocation.awareness.attributes指定的值,如這個值設置為了zone,那么preference=zone的話就在awareness.attributes=zone*這樣的節點搜索,如zone1、zone2。關於這個值作用可以參考下面文章。 
雖然es有提供這5種優先級,但感覺還是不能滿足我的需求,我是想能指定在某一個或多個節點中查詢,比如node1和node2里面的分片能組成一個完整的索引,那我可以只在node1和node2中搜索就行了。看來只能改源碼解決,改源碼也非常簡單。 
首先找到org.elasticsearch.cluster.routing.operation.plain.PlainOperationRouting這個類,es搜索時獲取分片信息是通過這個類的。它的preferenceActiveShardIterator()方法就是根據條件來找出響應的分片。看源碼可知其主要是根據preference這個參數來決定取出的分片的。如果沒有指定該參數,就隨機抽取分片進行搜索。如果參數以_shards開頭,則表示只查詢指定的分片。注意,這個功能官網的文檔中沒有寫到。 
然后下面就是判斷我上面說的5種優先級情況。我們現在要加個多節點分片查詢的功能,仿照單個節點分片查詢(指_only_node)就行了,在
 
Java代碼   收藏代碼
  1. if (preference.startsWith("_only_node:")) {  
  2.     return indexShard.onlyNodeActiveShardsIt(preference.substring("_only_node:".length()));  
  3. }  

后面加上  
Java代碼   收藏代碼
  1. if (preference.startsWith("_only_nodes:"))  {  
  2.     return indexShard.onlyNodesActiveShardsIt(preference.substring("_only_nodes:".length()));  
  3. }  

onlyNodesActiveShardsIt這個方法在org.elasticsearch.cluster.routing.IndexShardRoutingTable中是沒有的,要自己寫。加上  
  
Java代碼   收藏代碼
  1.    
  2. /** 
  3.  * Prefers execution on the provided nodes if applicable. 
  4.  */  
  5.  public ShardIterator onlyNodesActiveShardsIt(String nodeIds) {  
  6.      String[] ids = nodeIds.split(",");  
  7.      ArrayList<ShardRouting> ordered = new ArrayList<ShardRouting>(shards.size());  
  8.      // fill it in a randomized fashion  
  9.      for (int i = 0; i < shards.size(); i++) {  
  10.          ShardRouting shardRouting = shards.get(i);  
  11.          for(String nodeId:ids){  
  12.            if (nodeId.equals(shardRouting.currentNodeId())) {  
  13.              ordered.add(shardRouting);  
  14.            }  
  15.          }  
  16.      }  
  17.      return new PlainShardIterator(shardId, ordered);  
  18.  }  

重新編譯源碼就行了。查詢時加上preference=_only_nodes:node1id,node2id 就可以指定在node1和node2中搜索


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM