本章主要介紹ES的分布式架構(gòu)狸捅,ES的分布式存儲主要依賴于分片攻人, 分片又分為主分片和副本分片
Primary Shard(主分片)
Primary Shard可以將索引的數(shù)據(jù)分散到多個Data Node上沐批, 實現(xiàn)存儲的水平擴展,主分片個數(shù)在索引創(chuàng)建的時候指定,后續(xù)默認不可更改,如果要更改兴溜,必須重建索引。
Replica Shard(副本分片)
Replica Shard的引入是為了提高數(shù)據(jù)可用性耻陕。一旦主分片丟失拙徽,副本分片可以晉升到主分片。副本分片可以動態(tài)調(diào)整的诗宣。副本分片可以服務(wù)于讀請求膘怕,因此通過增加副本分片可以提升系統(tǒng)的整體吞吐量。
分片數(shù)的設(shè)置要合理
主分片數(shù)過小召庞,集群無法通過增加節(jié)點實現(xiàn)索引數(shù)據(jù)的擴展岛心。主分片數(shù)過大,會導致單個分片的容量過小篮灼,一個節(jié)點上有過多分片忘古,影響性能。
副本分片的設(shè)置過多影響集群的整體寫入性能穿稳。
故障轉(zhuǎn)移
下圖集群有三個節(jié)點組成存皂,一個索引包含三個主分片, 每個主分片的副本數(shù)是1逢艘。
上圖中節(jié)點1是master節(jié)點,節(jié)點1出現(xiàn)故障之后骤菠,集群重新選舉master節(jié)點它改。Node 3中的R0變成了P0,R0和R1重新分配商乎。
分片的內(nèi)部原理
分片(Shard)實際上是一個Lucene的實例央拖,從文件系統(tǒng)表現(xiàn)上看就是存儲了一系列文件的目錄。一個Shard由許多獨立的Segment組成, Segment中包含了文檔中的字典鹉戚、倒排索引鲜戒。所有的Segments數(shù)據(jù)都存儲_<segment_name>.cfs
的文件中。
隨著索引數(shù)據(jù)的不斷增長抹凳,segment數(shù)量也會逐漸變多遏餐,查詢性能也會降低,ES內(nèi)部會開啟一個線程將小的Segment合并成大的Segment赢底,減少碎片化失都,降低文件打開數(shù)量柏蘑,提升IO性能。
Segment 文件是不可變更的粹庞。當一個 Document 更新的時候咳焚,實際上是將舊的文檔標記為刪除,然后索引一個新的文檔庞溜。在 Merge 的過程中會將舊的 Document 刪除掉革半。具體到文件系統(tǒng)來說,文檔 A 是寫入到 <segment_name>.cfs 文件里的流码,刪除文檔 A 實際上是在<segment_name>.del文件里標記某個 document 已被刪除又官,那么下次查詢的時候則會跳過這個文檔,是為邏輯刪除旅掂。當歸并(Merge)的時候赏胚,老的 segment 文件將會被刪除,合并成新的 segment 文件商虐,這個時候也就是物理刪除了觉阅。
ES的并發(fā)控制
ES通過樂觀鎖的方式控制并發(fā)。ES中的文檔是不可變更的秘车,當你更新一個文檔時典勇,ES把原來文檔標記為刪除,增加一個全新的文檔叮趴,其中version字段加1.
- 內(nèi)部版本控制
新版ES中通過if_seq_no+if_primary_term的方式完成控制割笙。假設(shè)有如下的seq_no = 2, primary_term=2的文檔
如果我們用下面的方式更新文檔
PUT /blogs/_doc/1?if_seq_no=0&if_primary_term=1
{
"title": "Quick brown rabbits !!!",
"body": "Brown rabbits are commonly seen."
}
這個時候就會報錯。
為什么加一個if_primary_term眯亦?
對于if_primary_term記錄的就是具體的哪個主分片伤溉,而if_seq_no這個參數(shù)起的作用和舊版本中的_version是一樣的,之所以加上if_primary_term這個參數(shù)主要是提高并發(fā)的性能以及更自然妻率,因為每個document都只會在某一個主分片中乱顾,所以由所在主分片分配序列號比由之前通過一個參數(shù)_version,相當于由整個ES集群分配版本號要來的更好宫静。
- 外部版本控制
如果你的ES只是同步外部數(shù)據(jù)庫用作搜索走净,那么通過version+version_type=external完成并發(fā)控制,version可以是存在數(shù)據(jù)庫中的版本號孤里。 下面的例子中有個version=100的文檔伏伯。
如果采用下面version小于100的方式更新就會報錯
PUT /blogs/_doc/2?version=10&version_type=external
{
"title": "Keeping pets healthy",
"body": "My quick brown fox eats rabbits on a regular basis."
}