Elasticsearch 基本原理及規劃

Jeff Yen
13 min readDec 7, 2020

shard概念和如何規劃Elasticsearch cluster

分兩個部分

  1. 簡單shard原理和理念
  2. 根據Elasticsearch官訪研討會影片來規劃Elasticsearch cluster

Shard

在探討elasticearch sharding之前,我們要知道為什麼需要shard,假設有一個1 TB的資料,然後cluster裡面只有兩個容量512GB data node,如果我們不拆掉index的話,是沒有空間存放單一的index,所以我們必須使用shard的功能來處理這個問題。

shard 包含一部分index data,每一個shard 對應一個Lucene Index,它也有獨立和完整的功能,其中一個好處是可以shards分配到專門到儲存到專門的data node,然後配備SSD來處理。

https://codingexplained.com/coding/elasticsearch/understanding-sharding-in-elasticsearch

sharding有兩個很重要的優點

  1. 你可以很輕鬆的擴增資料,不用擔心某一天某一個index爆量,然後儲存的硬碟空間不足,還可以很方便規劃每一個index’s shard的規則
  2. 你可以分配一個index到多個node上,也等於多台機器去分擔一個 query,可以提高效能。
https://codingexplained.com/coding/elasticsearch/understanding-sharding-in-elasticsearch

只有在一開始建立index的時候可以指定primary_shard的數量,事後是沒有辦法修改shard數量,只能建立新的index,然後再搬遷到新的index。

https://codingexplained.com/coding/elasticsearch/understanding-sharding-in-elasticsearch

Elasticsearch 是透過routing 決定document要分配到哪一個shard,hash函數將routing值hash後生成一個數字,然後將這個數字除以primary_shard的數量得到餘數(0 ~”number_of_primary_shard- 1"),routing預設是document的_id,假設document id = 123,有四個primary shard

shard = hash(routing) % number_of_primary_shard>>> hash(125) % 6
5

這筆document 就會在primary_shard E這個 shard上,確保 document 均勻的分散到 primary shard 中。

這也解釋了建立完index,不能更改primary_shard的數量,因為更改primary_shard的數量後,之前建立的routing都會無效,無法找到document正確的shard。

Replication

大部分時間elasticsearch都會做Replication做副本,下圖就是依照1TB 做4個 primary_shard和4個 replication_shard,相同的shard ex: shard A, replica A是絕對不會放在同一個node上,但是node夠多的情況下,有可能會發生一個node上只有replication_shard或者primary_shard的情況。

https://codingexplained.com/coding/elasticsearch/understanding-replication-in-elasticsearch

replication有兩個很重要的目的

  1. 當然是高可用性,避免其中一個節點掛掉的時候影響整個cluster的運作,所以會避免primary_shard和replication_shard放在同一節點上。
  2. replication也有附帶提高查詢的效率,是因為查詢也會在所有的replication_shard上執行。

規劃elasticsearch

我下面所提到的資料為2016年的,可能現在的Elasticsearch效能有所提升,但我還是以該影片所提到內容所規劃。

到底disk要準備多大???

我們要先知道資料生成的流程,data 會先轉換成 json data 再根據mapping轉換成index,然後最後會依照你有幾個index和幾個replica來算出總共需要多少空間。

https://speakerdeck.com/elastic/quantitative-cluster-sizing?slide=19

如果只是單純資料結構的話,100GB資料會轉換成 60GB index,如果是先mapping好每個欄位名稱和類型,可以再減少30%的用量。如果使用其他混合的資料結構(裡面有其他欄位要給elasticsearch處理),因為還要對資料組合處理,資料轉換成index的效率就沒有單純資料結構來得好。影片22:00

https://speakerdeck.com/elastic/quantitative-cluster-sizing?slide=20

到底一個index要分配幾個shards???

在最新的版本(ES 7.x),Elasticsearch 預設一個index建立各一個 primary shard 和 replica shard。

官方也提到沒有一個標準的的公式來決定shard的大小或數量,要長期間的觀察和分析,也要想到在kibana執行查詢的時候,自己期望的時間是多久,下面那條基準線也是演講者在只有一個節點情況希望kibana的執行時間為500m/s而畫出來的。

https://speakerdeck.com/elastic/quantitative-cluster-sizing?slide=23

Shards 的數量跟index有關,依照每一個不同的index使用頻率和大小可以決定不同的primary shard數量,假如一個index大小超過100GB,那可能要切到4~5個shards,而不是你有幾個node決定,官方的影片也有提到假如在一個節點上,從一個shard提升到兩個shards效能有比較明顯的提升,再多反而會效能下降,建議是一個node上一個primary shard 和 replica shard就可以了。

https://speakerdeck.com/elastic/quantitative-cluster-sizing?slide=26

Replicas shard 主要是為了提升search的效能,可以隨時添加和刪除,為了更高的可用性和吞吐量,建議至少兩個replicas shard。

設定完Elasticsearch cluster不應該更改shards數量,如果要更改只有兩個方法,一個是Reindex,這個雖然很久但是不用停機,另一個是Shrink Index API,用來減少index。

Shard 本質就是Lucene index,大量的small shards可以提昇shard處理速度,但是查詢過程中,有一個shard合併的過程,如果shard數不斷的增加,合併的時間則會增加,而且隨著更多的任務需要按順序排隊和處理,影響整個cluster效能和吞吐量,如果有多個併發查詢會很明顯。

最大的JVM heap size為30–32GBXms and Xms值要相同,防止程式在執行時改變堆記憶體大小,這是一個很耗系統資源的過程。而且不要超過實體RAM 50%,剩下的RAM要做cache,不論實際的JVM heap size為多少,1G的JVM heap對應到20個shards,所以上限就是32*20=640個shards,shard size 官方建議是10GB ~ 50GB

一個 Index 有多個 primary shard 時,主要的目的就是為了 indexing 時能有更多的 Nodes 能分擔處理,避免不同的 Shard 都被分配在同一台 Node 身上,因為這樣會會彼此競爭該節點的資源。
可以透過index.routing.allocation.total_shards_per_node設定,來限制每個 node 可以被分配存放這個 index 多少個 shard

PUT /my-index-000001/_settings 
{
"index" : {
"routing.allocation.total_shards_per_node" : 5
}
}

通常index會設定為time-based indices,最常見就是Daily indices,因為這是最容易是設定生命週期。

到底一個cluster要怎麼規劃???

在影片的第四部分28:10左右,講到多個nodes的情況下要怎麼規劃,也就是cluster的狀況下,避免影響到現有的prod環境下,可以先準備有兩個data node的cluster做測試,一個primary_shard和一個replication_shard,做測試的時候index request也會依照node減少而改變。

下一步演講者會講indexing rate,單純資料結構和混合的資料結構的indexing rate都會因為event的大小而成反比,在吞吐量上面,混合的資料結構在最大的event下會得到最佳的吞吐量,最小而反之。

這裡先各準備了800GB的資料在兩個data node上,第一次先query了100GB的資料,第二次query200GB的資料,直到第八次query全部的800GB資料,在Dashborad Latency提高主要跟garbage collection和很多的merge,同時也不斷測試index rate,而最上面的achieved index limit是跟 numbers of request 有相關。

在query500GB時候,可以特別看到兩件事情,第一件事是看到query latency有提升,第二件事是achieved index rate下降,通常是達到系統資源的極限,因為archieved和indexing行為也會用到很多CPU,也可以看到在querying少量資料的時候,index rate相當的不錯。

影片的最後也有提到一個簡單的benchmark,假如準備1TB的儲存空間和設定保存十五天,大該每一天可以每一天可以使用68GB的index,一秒可以接受700 events,大該一天可以接收89GB的json格式的log,當然而外的設定會影響到實際的效用。

影片後面的問答也值得一看,有人直接問在production下到底最多可以幾個nodes ?到底cluster超過一百的node常不常?專家的期望是什麼?這裡我就不破梗了。

我這裡也提供官方的影片,我文章很多內容從這裡翻譯的。

--

--