#Elasticsearch學習筆記(三)Elasticsearch集群分片的讀寫操作流程
在上篇文章中詳細介紹了Elasticsearch基于Lucene的單節點的準實時索引的實現,那么Elasticsearch是如何解決分布式下面的CRUD操作的呢?
## 1、路由計算(routing)和副本一致性(replica)
**routing**
Elasticsearch針對路由計算選擇了一個很簡單的方法,計算如下:
routing = hash(routing) % number_of_primary_shards
每個數據都有一個routing參數,默認情況下,就使用其_id值,將其_id值計算hash后,對索引的主分片數取余,
就是數據實際應該存儲到的分片ID
由于取余這個計算,完全依賴于分母,所以導致Elasticsearch索引有一個限制,索引的主分片數,不可以隨意修改。因為一旦主分片數不一樣,索引數據不可讀。
副本一致性(replica)
作為分布式系統,數據副本可算是一個標配。Elasticsearch數據寫入流程。自然涉及副本,在有副本配置的情況下,數據從發向Elasticsearch節點,到接到Elasticsearch節點響應返回,流向如下

1)客戶端請求發送給Node1節點,這里也可以發送給氣他節點
2)Node1節點用數據的_id計算出數據應該存儲在shard0上,通過cluster state信息發現shard0的主分片在Node3節點上,Node1轉發請求數據給Node3,Node3完成數據的索引,索引過程在上篇博客中詳細介紹了。
3)Node3并行轉發數據給分配有shard0的副本分片Node1和Node2上。當收到任一節點匯報副本分片數據寫入成功以后,Node3即返回給初始的接受節點Node1,宣布數據寫入成功。Node1成功返回給客戶端。
新建、索引和刪除都是寫(write)操作,他們必須在主分片上成功完成才能賦值到相關的復制分片上。
replication:通過在客戶端發送請求的URL中加入?replication=async,可以控制Node3在完成本機主分片寫入后,就返回給Node1宣布寫入成功。這個參數在2.0版本中已經被廢棄
consistency:默認主分片在嘗試寫入時需要規定數量(quorum)或過半的分片(可以使主分片或復制分片)寫入成功,就返回給客戶端。consistency允許為one(只有一個主分片,與上面的replication等同)
`int((primary+number_of_replica) / 2) +1`
默認只有一個分片,那么就必須要兩個活動分片,當然,這個默認設置將阻止我們在單一節點集群中進行操作。為了避開這個問題,規定數量只有在number_of_replicas大于1時才生效,也就是默認分片情況下不生效。
timeout:如果集群出現異常,有些分片當前不可用,Elasticsearch默認會等待1分鐘,看分片能否恢復,
副本設置和分片設置不一樣,是可以隨時調整的,有些較大的索引,甚至可以做optimize之前,先把副本全部取消掉,等optimize完成后,再重新打開開啟副本,節約單個segment的重復歸并消耗。
## 2、shard的allocate配置
上文介紹了分片的索引過程,通過路由計算可以確定文本所在的分片id,那么分片在集群中的分配策略是如何確定的?
一般來說,某個shard分配在哪個節點上,是由Elasticsearch自動決定的。以下幾種情況會觸發分配動作。
- 新索引生成。
- 索引的刪除
- 新增副本分片
- 節點增減引發的數據均衡
Elasticsearch還提供了一系列參數詳細控制這部分邏輯:
cluster.routing.allocation.enable參數用來允許分配哪種分片。默認是All,可選項還包括primaries和new_primaries。none則徹底拒絕分片。
cluster.routing.allocation.allow_rebalance參數用來控制什么時候允許數據均衡。默認是indices_all_active,即要求所有分片都正常啟動成功以后,才可以進行數據均衡操作,否則的話,在集群重啟階段,會浪費太多流量了。
cluster.routing.allocation.cluster_concurrent_rebalance參數用來控制集群內同時啟動的數據均衡任務個數。默認是2個。