該文章同步發佈於:我的部落格
也歡迎關注我的 Facebook 以及 Instagram 接收軟體相關的資訊!
上一篇文章 中我們示範了如何使用 Kibana 的 DevTools 利用 REST API 來和 Elasticsearch 進行溝通。
而今天這篇文章則會帶大家理解 Elasticsearch 如何做 Sharding ( 分片 ) 這件事。
首先,Elasticsearch 的 sharding 分成 primary shard
以及 replica shard
兩種,這篇文章主要講解 primary shard。
試想一下,我們有一個 800GB 的 index,但我們的機器硬體只有 500GB,這時候有兩種選項,把機器的硬體升級到 1TB,或是再開一個 500GB 的機器分攤這 800GB 的 index。
而升級機器硬體是最簡單也是最粗暴的,有時候可以花錢解決的事情就花錢解決最好,但最怕就是花錢沒有花到刀口上。
花錢還有一個缺點,持續地升級機器,花費是非線性成長,有可能 500GB 到 1TB 的價格是 3 個 500GB 機器的價格,而這時候稍微動點腦筋,不僅僅可以降低花費,還能提高效率,何樂而不為?
甚至最慘的就是花錢升級到一個極限,Elasticsearch 還是負擔不了對一個超大的 index 做搜尋。
所以 Primary Shard 要做的事情,就是把 800GB 的 index 拆分成 2 個 400GB,或是 4 個 200GB 的 index 儲存,這樣就可以透過水平擴展機器的方式來吃下這 800GB 的 index,就像下圖這樣:
關於分片,現在只需要了解:
Apache Lucene index 延伸閱讀:What is Apache Lucene?
好處:
接著回到 Kibana 的 DevTools,一樣輸入 GET /_cat/indices?v&expand_wildcards=all 得到結果,會看到 header 上有一個 pri
的值,其實就是說明了 primary shard 的數量。
在 Elasticsearch 7.0 以前,每一個 index 都預設配備 5 個 primary shard,而在這 7.0 之後被拔除了,因為造成了 over-sharding 的議題。
明明資料量不大,但卻硬要切分成 5 個 shard,要知道的是每一個 shard 其實也有很多需要被記錄的 metadata
,而當資料量很小,又 over-sharding 的情況,反而會吃掉更多的沒必要被吃掉的記憶體。
所以在 7.0 之後,預設都是只有一個 primary shard。
那我們想要增加 Shard 的數量該怎麼做呢?最直覺的想法是,建立一個新的 index 然後把舊的複製過去,但這是一個很辛苦也很考驗資料正確性的工作,所以 Elasticsearch 有提供 Split
的 API 讓我們可以針對現有的 index 做切割的動作。
使用 Split API 關乎到 number_of_routing_shards 的設定,也牽扯到 number_of_shards 的設定,有興趣可以閱讀官方文件
能不能夠切割 Primary shard 的重點在於一開始對於 primary shard 的設定,當一開始就限制了 shard 的數量,也不能使用 split API,還是要乖乖走複製的路
而可以做切割,當然也有縮小的選項,就是使用 Shrink
API 來縮小 shard 的數量。
看到這邊常常會有一個問題浮現出來,那就是:
多少的 shard 是最好的?我該怎麼在一開始就設定好呢?
這種東西真的沒有一個公式可以去套用,完全取決於機器的硬體設備,nodes 的數量,index 的大小,甚至是查詢的應用場景等等。
當然如果你一開始就知道這會是一個至少百萬筆 documents 的 index,那一開始就做 3 ~ 5 個的 primary shard 也沒有不行。
或是走一個且戰且看的狀態,使用預設的設定,需要 shard 的時候在進行 split 也可以。
這種時候反而更能展現出工程師的價值,我們可以替未來可能會發生的事情提前做好準備,甚至還可以在早期替團隊省下不必要的花費,只要我們真的理解如何去做分片,以及什麼時候分片會比較恰當。
軟體開發一直都是一種取捨,很難找到那個 『 黃金數字 』 讓我們每次都可以參照。