Elasticsearch 學習二(請求流程).

一、寫入數據

1、ES 的任意節點都可以作為協調(Coordinating)節點接受請求(包括新建、索引或者刪除請求),每個節點都知道集群中任一文檔位置;

2、協調節點會通過 routing 欄位計算出一個主分片(primary shard),並把請求路由到主分片所在節點(routing 是一個可變值,默認是文檔的 _id) ;

shard = hash(routing) % number_of_primary_shards

tips:這就解釋了為什麼我們要在創建索引的時候就確定好主分片的數量,並且永遠不會改變這個數量:因為如果數量變化了,那麼所有之前路由的值都會無效,文檔也再也找不到了。

3、在主分片節點上,數據會先被寫入(index buffer)中,同時寫入 translog,這個時候數據還不能被搜索到(這個也是 es 是近實時搜索的原因);

tips:整個過程大部分在記憶體中,如果斷電就會導致數據丟失。因此,ES 引入了 translog,數據寫入記憶體時,會同時寫入 translog(會立即落盤),來保證數據不丟失。

4、經過一段時間(默認 1s)或者 index buffer 滿了(默認 jvm 的 10%),會將 index buffer 中的文檔 refresh 到系統文件快取(os cache),然後再刷入到 lucene 的底層文件 segment 中,同時建立倒排索引,這個時候文檔是可以被搜索到的;

5、 由於 segment 的不可變性,隨著 segment 越來越多,每打開一個 segment 就會消耗一個文件句柄,導致查詢性能越來越差。這時,ES 後台會有一個單獨執行緒專門合併 segment,將零碎的小的 segment 合併成一個大的 segment;

6、經過一段時間(默認30 min)或者 tanslog 滿了(默認512M),會將文件系統快取的 segment 落盤;

7、如果主分片所在的節點請求執行成功,它會將請求同步轉發到副本分片所在節點,做到主副數據的一致性,一旦所有的副本分片都報告成功,主分片節點將向協調節點報告成功,協調節點向客戶端報告成功。因此,數據寫入,主副本之間採用的是同步寫入過程。

tips:寫一致性默認的策略是 —— Quorum ,即大多數的分片副本狀態沒問題才允許執行寫操作。

8、當集群中某個節點宕機,該節點上所有分片中的數據全部丟失(既有主分片,又有副分片);丟失的副分片對數據的完整性沒有影響,丟失的主分片在其他節點上的副分片會被選舉成主分片;所以整個索引的數據完整性沒有被破壞。

9、如果是刪除操作,refresh 的時候就會生成一個 .del 文件,邏輯刪除,將這個 document 標識為 deleted 狀態,在搜索的搜索的時候就不會被搜索到了。

10、如果是更新操作,就是將原來的 document 標識為 deleted 狀態,然後新寫入一條數據。

二、查詢數據

GET my-index/_doc/0

1、ES 的任意節點都可以作為協調(Coordinating)節點接受請求,每個節點都知道集群中任一文檔位置;
2、協調節點對 id 進行路由,從而判斷該數據在哪個 shard,然後將請求轉發給對應的節點,此時會使用隨機輪詢演算法,在 primary shard 和 replica shard 中隨機選擇一個,讓讀取請求負載均衡,
3、處理請求的節點返回 document 給協調節點。
4、協調節點,返回 document 給客戶端。

三、檢索數據

GET /my-index/_search
{
  "query": {
    "match_all": {}
  }
}

1、ES 的任意節點都可以作為協調(Coordinating)節點接受請求,每個節點都知道集群中任一文檔位置;
2、協調節點進行分詞等操作後,去查詢所有的 shard 節點。
3、所有 shard 將滿足條件的數據(id、排序欄位等)資訊返回給協調節點。
4、協調節點將數據重新進行排序,獲取到真正需要返回的數據的 id。
5、協調節點再次請求對應的 shard (此時有 id 了,可以直接定位到對應shard)。
6、獲取到全量數據,返回給客戶端。

tips: ES 要盡量避免深度分頁查詢,因為每個 shard 都會返回 from+size 的數據。比如我們要每頁顯示 10 條,查詢第 10000 頁數據,那麼每個分片就要返回10010 條數據,協調節點要處理更多的數據,這會嚴重的影響性能。

參考博文:

  1. 分散式系統的 Quorum 策略
  2. 協調節點
Tags: