前言
了解分片的基本原理,對Elasticsearch性能調(diào)優(yōu)有幫助。
關(guān)系梳理
ES底層使用的是Lucene庫,ES的分片(shard )是Lucene的索引,ES的索引是分片的集合,Lucene的索引是由多個段(segment)組成。
段(segment)
Per-segment search,也即按段搜索,是Lucene中的概念。每個段本身就是一個倒排索引,Lucene中的索引除了表示段的集合外,還增加了提交點的概念,一個提交點就是一個列出了所有已知段的文件。
Per-segment search的工作流程如下:
- 新的文檔首先被寫入內(nèi)存區(qū)的索引緩存(buffer)。
- 不時,這些buffer被提交。
- 新段被打開,它包含的文檔可以被檢索。
- 內(nèi)存的緩存被清除,等待接收新的文檔。
提交
一次完整的提交會將段刷到磁盤,并寫入一個包含所有段列表的提交點。ES在啟動或重新打開一個索引的過程中使用這個提交點來判斷哪些段隸屬于當(dāng)前分片。
不可變性
寫入磁盤的倒排索引是不可變的,也即段是不可改變的,所以既不能把文檔從舊的段中移除,也不能修改舊的段來更新文檔。取而代之的是,每個提交點會包含一個 .del 文件,它記錄了段中被刪除的文檔。
當(dāng)一個文檔被 “刪除” 時,它實際上只是在 .del 文件中被標(biāo)記為刪除。一個被標(biāo)記為刪除的文檔仍然可以被查詢匹配到,但它會在最終結(jié)果被返回前從結(jié)果集中移除。
文檔更新也是類似的操作方式:當(dāng)一個文檔被更新時,舊版本文檔被標(biāo)記為刪除,文檔的新版本被索引到一個新的段中。 可能兩個版本的文檔都會被一個查詢匹配到,但被刪除的那個舊版本文檔在結(jié)果集返回前會被移除。
近實時搜索
提交一個新的段到磁盤需要調(diào)操作系統(tǒng)的fsync方法,確保段被物理地寫入磁盤,即使斷電也不會丟失數(shù)據(jù)。但是fsync是昂貴的,它不能在每個文檔被索引時就觸發(fā)。所以需要一種更輕量級的方式使新的文檔可以被搜索。
位于ES和磁盤間的是文件系統(tǒng)緩存。在內(nèi)存索引緩存中的文檔被寫入新的段,新的段首先寫入文件系統(tǒng)緩存,這代價很低,之后會被同步到磁盤,這代價很大。一旦一個文件被緩存,它也可以被打開和讀取,就像其他文件一樣。
Refresh
在ES中,refresh是指這樣一個過程:將In-memory buffer中的文檔寫入到文件系統(tǒng)緩存中新的段,新的段被打開(可被搜索)。默認(rèn)情況下每個分片會每秒自動刷新一次。文檔在In-memory buffer中是不能被搜索的,寫入到段里面才能被搜索。這就是為什么我們說Elasticsearch是近實時搜索: 文檔的變化并不是立即對搜索可見,但會在一秒之內(nèi)變?yōu)榭梢姟?/p>
Flush
在ES中,進行一次提交并刪除事務(wù)日志的操作叫做flush。一些老資料說ES每30分鐘flush一次,或者事務(wù)日志過大也會flush。官網(wǎng)最新的說法是ES根據(jù)需要自動觸發(fā)刷新,主要取決于事務(wù)日志的大小和權(quán)衡執(zhí)行flush的成本。也可以調(diào)用flush API主動flush。
Translog
Translog全稱transaction log(事務(wù)日志)。事務(wù)日志主要是為了防止在兩次提交之間的數(shù)據(jù)丟失。事務(wù)日志也被用來提供實時 CRUD ,當(dāng)你通過文檔ID查詢、更新、刪除一個文檔,在從相應(yīng)的段檢索之前, ES會首先檢查事務(wù)日志最新的改動,這意味著ES總是能夠通過文檔ID實時地獲取到文檔的最新版本。
事務(wù)日志并不是實時落盤的,而是定期刷到磁盤。所以事務(wù)日志其實也是存在丟失的可能性的。那么這里就有一個問題,既然調(diào)用fsync的提交是一種昂貴的操作,為了防止數(shù)據(jù)丟失引入了事務(wù)日志,但是事務(wù)日志也需要刷到磁盤才能保證數(shù)據(jù)不丟,那事務(wù)日志的意義何在?答案是事務(wù)日志的刷盤更輕量級,因為它調(diào)用的是fdatasync這個系統(tǒng)函數(shù),而不是fsync。感興趣的朋友可以了解下fsync和fdatasync的差別。
完整流程
我們將上述知識點串起來得到完整流程。
- 當(dāng)一個文檔被索引,它被加入到內(nèi)存緩存,同時寫入事務(wù)日志。
- 分片每秒都進行refresh。refresh后,內(nèi)存緩沖區(qū)的文檔被寫入到文件系統(tǒng)緩存;段被打開,使得新的文檔可以被搜索;緩存被清除。
- 更多的文檔加入到緩沖區(qū),寫入事務(wù)日志,這個過程會持續(xù)。
- 不時的,比如事務(wù)日志很大了,會進行一次全提交。內(nèi)存緩沖區(qū)的所有文檔會寫入到新的段中;緩沖區(qū)被清空;一個提交點寫入磁盤;文件系統(tǒng)緩存通過fsync操作flush到磁盤;事務(wù)日志被清除。
合并段
通過每秒自動刷新創(chuàng)建新的段,用不了多久段的數(shù)量就爆炸了。每個段都會消費文件句柄、內(nèi)存、CPU資源。更重要的是,每次搜索請求都需要依次檢查每個段。段越多,查詢越慢。
ES通過后臺合并段解決這個問題。小段被合并成大段,再合并成更大的段。合并段時會真正刪除被標(biāo)記為已刪除的文檔。舊的段不會再復(fù)制到更大的新段中。這個過程你不必做什么,當(dāng)你在索引和搜索時ES會自動處理。這個過程不會中斷索引和搜索。
兩個提交的段和一個未提交的段合并為了一個更大的段。
這期間發(fā)生一系列操作:新的段flush到了硬盤;新的提交點寫入新的段,排除舊的段;新的段打開供搜索;舊的段被刪除。
文章來源:http://www.zghlxwxcb.cn/news/detail-813741.html
合并大的段會消耗很多IO和CPU,如果不合并又會影響到搜索性能。默認(rèn)情況下,ES會限制合并過程,這樣搜索就可以有足夠的資源進行。optimize API可以強制合并段。文章來源地址http://www.zghlxwxcb.cn/news/detail-813741.html
到了這里,關(guān)于深入理解Elasticsearch分片的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!