什麼鬼?ES主分片和副本大小居然不一樣!

引言

很多認爲Elasticsearch(以下簡稱ES),同一個分片的主分片和副本分片文檔數量肯定是樣的,數據大小也是一樣的。

這個其實值說對了一半,文檔數量是一樣的沒錯,但是數據大小不一定一樣。

產生這種現象的原因在於,主分片和副本分片的segment數量可能不一樣。

正文

我們來看個示例。

以下的示例測試環境是ES 7.1.0版本

先插入4個文檔,

PUT my_blog/_doc/1
{
  "title" : "blog1",
  "content" : "this is blog1"
}


PUT my_blog/_doc/2
{
  "title" : "blog2",
  "content" : "this is blog2"
}


PUT my_blog/_doc/3
{
  "title" : "blog3",
  "content" : "this is blog3"
}

PUT my_blog/_doc/4
{
  "title" : "blog4",
  "content" : "this is blog4"
}

然後使用cat/shards命令看下索引的分片信息,

GET _cat/shards/my_blog?v

結果如下圖

在這裏插入圖片描述

可以很清楚的看到,主分片和副本分片雖然文檔數量都是4,但是大小一個是15.7KB,一個是11.9KB。前面說了原因,是因爲主副分片中的segment數量不一樣導致的。我們來證實下。

使用cat/segment命令來查看分片的segment信息,

GET _cat/segments/my_blog?v

結果如下圖

在這裏插入圖片描述

從結果中可以很明顯看出副本分片上的segment數量比主分片少了一個。這就是造成數據大小不一樣的“真兇”。

通常情況下,這種不一致並沒有什麼影響。ES會幫我們自動處理好分片上segment的數量。當然我們也可以通過ES的force merge命令,強制把分片上的segment合併成指定的數量。

POST my_blog/_forcemerge?max_num_segments=1

max_num_segments 參數用來指定最終要合到的segment數量。

通過上面這個命令,我們強制索引合併segment到一個。然後再次用cat/segment看下分片信息,

在這裏插入圖片描述

這樣我們的主副分片都只有一個segment了。大小自然是一樣的。

知識延伸

ES在寫入(index)數據的時候,是先寫入到緩存中。這時候數據還不能被搜索到。默認情況下ES每隔1秒會執行refresh操作,從內存buffer中將數據寫入os cache(操作系統的內存),產生一個segment file文件。同時建立倒排索引,這個時候文檔是可以被搜索到的。

每次refresh都會生成一個新的segment,那麼segment的數量很快就會爆炸。另外就是每次搜索請求都必須訪問segment,理論上segment越多,搜索請求就會變的越慢。

ES有一個後臺進程專門負責segment的合併,它會把小segments合併成更大的segments。這個merge操作大部分時候我們並不需要關心,ES自動處理什麼時候merge。只要不影響查詢性能,我們也不需要關係分片上有多少個segment。

在這裏插入圖片描述

在這裏插入圖片描述

不過對於一些業務場景,索引是按照天,周,或者月建立的,如果一些老的索引已經停止寫入或者更新,我們可以通過執行一次force merge來強制該索引合併到一個大的segment上,提高搜索的效率。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章