Elasticsearch原理學習(五)分片原理

分片是 Elasticsearch 最小的工作單元。一個分片其實就是一個lucene索引析既,眾多的分片組合在一起是一個完整的elasticsearch索引攒盈。

一、倒排索引

傳統(tǒng)數(shù)據(jù)庫的索引方式并不適用于大數(shù)據(jù)量的全文檢索直撤,且數(shù)據(jù)庫的索引隨著數(shù)據(jù)量增加,仍然存在索引效率變低的問題蜕着。

在第一章節(jié)中我基于lucene的角度分析了倒排索引的原理谋竖,關(guān)于具體內(nèi)容可參考http://www.reibang.com/p/733fc580e696。Elasticsearch 使用一種稱為倒排索引的結(jié)構(gòu)承匣,它適用于快速的全文搜索蓖乘。

當存儲數(shù)據(jù)時,將數(shù)據(jù)中的關(guān)鍵詞拆分并提取建立索引(就像詞典的目錄一樣)韧骗;
當查詢的時候嘉抒,會根據(jù)查詢的內(nèi)容在目錄中尋找,直到找到查詢內(nèi)容所在的文檔袍暴。

優(yōu)點:
1)準確率高
2)不會因為數(shù)據(jù)量的增加導致查詢速度大幅下降些侍。(無論是中文還是英文詞典而言,作為目錄的數(shù)量是固定的政模,基本沒有變化岗宣,即使數(shù)據(jù)量增大了,目錄還是那么多)

缺點:
索引文件占用額外的硬盤空間淋样。

使用場景:
適合海量數(shù)據(jù)的查詢耗式。

二、動態(tài)更新索引

早期的全文檢索會為整個文檔集合建立一個很大的倒排索引并將其寫入到磁盤趁猴。 一旦新的索引就緒刊咳,舊的就會被其替換。

倒排索引被寫入磁盤后是 不可改變 的:它永遠不會修改儡司。

不變性具有哪些價值娱挨?
1)不需要鎖。如果你從來不更新索引枫慷,你就不需要擔心多進程同時修改數(shù)據(jù)的問題让蕾。
2)性能提升浪规。一旦索引被讀入內(nèi)核的文件系統(tǒng)緩存,便會留在哪里探孝,由于其不變性笋婿。只要文件系統(tǒng)緩存中還有足夠的空間,那么大部分讀請求會直接請求內(nèi)存顿颅,而不會命中磁盤缸濒。
3)寫入單個大的倒排索引允許數(shù)據(jù)被壓縮,減少磁盤 I/O 和 需要被緩存到內(nèi)存的索引的使用量粱腻。

不變性的缺點庇配?
如果你需要讓一個新的文檔 可被搜索,你需要重建整個索引绍些。這要么對一個索引所能包含的數(shù)據(jù)量造成了很大的限制捞慌,要么對索引可被更新的頻率造成了很大的限制。

如何在保留不變性的前提下實現(xiàn)倒排索引的更新柬批?
答案是: 用更多的索引啸澡。通過增加新的補充索引來反映新近的修改,而不是直接重寫整個倒排索引氮帐。每一個倒排索引都會被輪流查詢到嗅虏,從最早的開始查詢完后再對結(jié)果進行合并。

Elasticsearch 基于 Lucene, 這個 java 庫引入了 按段(segment)搜索的概念上沐。 每一段本身都是一個倒排索引皮服, 但索引在Lucene中除表示所有段的集合外, 還增加了提交點的概念参咙。

如下所示有當前有三個段龄广,有一個提交點指向這三個段:
commit point.png

模擬一個新文檔的創(chuàng)建過程:

  1. 新文檔被收集到內(nèi)存索引緩存
commit point (2).png
  1. 不時地, 緩存被提交
    (1) 生成一個新的段,追加的倒排索引被寫入磁盤昂勒。
    (2) 一個新的包含新段名字的提交點被寫入磁盤蜀细。
    (3) 磁盤進行同步,所有在文件系統(tǒng)緩存中等待的寫入都刷新到磁盤戈盈,以確保它們被寫入物理文件奠衔。
  2. 新的段被開啟,讓它包含的文檔可見以被搜索
commit point (3).png
  1. 內(nèi)存緩存被清空塘娶,等待接收新的文檔
commit point (4).png

當一個查詢觸發(fā)時归斤,所有已知的段按順序被查詢。詞項統(tǒng)計會對所有段的結(jié)果進行聚合刁岸,以保證每個詞和每個文檔的關(guān)聯(lián)都被準確計算脏里。 這種方式可以用相對較低的成本將新文檔添加到索引。

段是不可改變的虹曙,所以既不能從把文檔從舊的段中移除迫横,也不能修改舊的段來進行反映文檔的更新番舆。 取而代之的是,每個提交點會包含一個 .del 文件矾踱,文件中會列出這些被刪除文檔的段信息恨狈。

當一個文檔被 “刪除” 時,它實際上只是在 .del 文件中被 標記 刪除呛讲。一個被標記刪除的文檔仍然可以被查詢匹配到禾怠, 但它會在最終結(jié)果被返回前從結(jié)果集中移除。

文檔更新也是類似的操作方式:當一個文檔被更新時贝搁,舊版本文檔被標記刪除吗氏,文檔的新版本被索引到一個新的段中。 可能兩個版本的文檔都會被一個查詢匹配到雷逆,但被刪除的那個舊版本文檔在結(jié)果集返回前就已經(jīng)被移除弦讽。

三、近實時搜索

隨著按段(per-segment)搜索的發(fā)展关面,一個新的文檔從索引到可被搜索的延遲顯著降低了坦袍。新文檔在幾分鐘之內(nèi)即可被檢索,但這樣還是不夠快等太。磁盤在這里成為了瓶頸。提交(Commiting)一個新的段到磁盤需要一個fsync來確保段被物理性地寫入磁盤蛮放,這樣在斷電的時候就不會丟失數(shù)據(jù)缩抡。 但是 fsync 操作代價很大; 如果每次索引一個文檔都去執(zhí)行一次的話會造成很大的性能問題

我們需要的是一個更輕量的方式來使一個文檔可被搜索包颁,這意味著 fsync 要從整個過程中被移除瞻想。在 Elasticsearch 和磁盤之間是文件系統(tǒng)緩存。 像之前描述的一樣娩嚼, 在內(nèi)存索引緩沖區(qū)中的文檔會被寫入到一個新的段中蘑险。 但是這里新段會被先寫入到文件系統(tǒng)緩存這一步代價會比較低,稍后再被刷新到磁盤這一步代價比較高岳悟。不過只要文件已經(jīng)在緩存中佃迄,就可以像其它文件一樣被打開和讀取了。

Lucene允許新段被寫入和打開(內(nèi)存緩沖區(qū)中包含了新文檔的lucene索引)贵少,使其包含的文檔在未進行一次完整提交時便對搜索可見呵俏。這種方式比進行一次提交代價要小得多,并且在不影響性能的前提下可以被頻繁地執(zhí)行滔灶。

commit point (5).png

在Elasticsearch中普碎,寫入和打開一個新段的輕量的過程叫做refresh 。默認情況下每個分片會每秒自動刷新一次录平。這就是為什么我們說Elasticsearch是近實時搜索: 文檔的變化并不是立即對搜索可見麻车,但會在一秒之內(nèi)變?yōu)榭梢姟?/p>

這些行為可能會對新用戶造成困惑: 他們索引了一個文檔然后嘗試搜索它缀皱,但卻沒有搜到。這個問題的解決辦法是用 refresh API 執(zhí)行一次手動刷新: /users/_refresh动猬。

注意:盡管刷新是比提交輕量很多的操作啤斗,它還是會有性能開銷。當寫測試的時候枣察, 手動刷新很有用争占,但是不要在生產(chǎn)環(huán)境下每次索引一個文檔都去手動刷新。 相反序目,你的應(yīng)用需要意識到 Elasticsearch 的近實時的性質(zhì)臂痕,并接受它的不足 。

可以通過配置設(shè)置每個索引的刷新時間:

# 關(guān)閉自動刷新
PUT /users/_settings
{ "refresh_interval": -1 }
# 每一秒刷新
PUT /users/_settings
{ "refresh_interval": "1s" }

四猿涨、持久化

如果沒有用 fsync 把數(shù)據(jù)從文件系統(tǒng)緩存刷(flush)到硬盤握童,我們不能保證數(shù)據(jù)在斷電甚至是程序正常退出之后依然存在。為了保證 Elasticsearch 的可靠性叛赚,需要確保數(shù)據(jù)變化被持久化到磁盤澡绩。在動態(tài)更新索引,我們說一次完整的提交會將段刷到磁盤俺附,并寫入一個包含所有段列表的提交點肥卡。Elasticsearch 在啟動或重新打開一個索引的過程中使用這個提交點來判斷哪些段隸屬于當前分片。

但在兩次提交之間發(fā)生變化的文檔怎么辦事镣?我們也不希望丟失掉這些數(shù)據(jù)步鉴。Elasticsearch增加了一個translog ,或者叫事務(wù)日志璃哟,在每一次對Elasticsearch進行操作時均進行了日志記錄氛琢。、

此時新建索引的過程:

  1. 一個文檔被索引之后随闪,就會被添加到內(nèi)存緩沖區(qū)阳似,并且追加到了translog。
commit point (6).png
  1. 刷新(refresh)使分片每秒被刷新(refresh)一次:
    1)這些在內(nèi)存緩沖區(qū)的文檔被寫入到一個新的段中铐伴,且沒有進行fsync操作撮奏。
    2)這個段被打開,使其可被搜索盛杰。
    3)內(nèi)存緩沖區(qū)被清空挽荡。
commit point (7).png
  1. 這個進程繼續(xù)工作,更多的文檔被添加到內(nèi)存緩沖區(qū)和追加到事務(wù)日志即供。
commit point (8).png
  1. 每隔一段時間定拟,translog變得越來越大,索引被刷新(flush);一個新的translog被創(chuàng)建青自,并且全量提交被執(zhí)行株依。
    1)所有在內(nèi)存緩沖區(qū)的文檔都被寫入一個新的段。
    2)緩沖區(qū)被清空延窜。
    3)一個提交點被寫入硬盤恋腕。
    4)文件系統(tǒng)緩存通過 fsync 被刷新(flush)。
    5)老的translog被刪除逆瑞。
commit point (9).png

translog 提供所有還沒有被刷到磁盤的操作的一個持久化紀錄荠藤。當 Elasticsearch 啟動的時候, 它會從磁盤中使用最后一個提交點去恢復已知的段获高,并且會重放 translog 中所有在最后一次提交后發(fā)生的變更操作哈肖。

translog 也被用來提供實時 CRUD 。當你試著通過 ID 查詢念秧、更新淤井、刪除一個文檔,它會在嘗試從相應(yīng)的段中檢索之前摊趾, 首先檢查 translog 任何最近的變更币狠。這意味著它總是能夠?qū)崟r地獲取到文檔的最新版本。

執(zhí)行一個提交并且截斷translog的行為在Elasticsearch被稱作一次 flush砾层,分片每 30 分鐘被自動刷新(flush)漩绵,或者在 translog 太大的時候也會刷新

translog 的目的是保證操作不會丟失肛炮,在文件被 fsync 到磁盤前渐行,被寫入的文件在重啟之后就會丟失。默認 translog 是每 5 秒被 fsync 刷新到硬盤铸董, 或者在每次寫請求完成之后執(zhí)行(e.g. index, delete, update, bulk)。這個過程在主分片和復制分片都會發(fā)生肴沫。

但是對于一些大容量的偶爾丟失幾秒數(shù)據(jù)問題也并不嚴重的集群粟害,使用異步的 fsync還是比較有益的。你需要 保證 在發(fā)生 crash 時颤芬,丟失掉 sync_interval 時間段的數(shù)據(jù)也無所謂悲幅。如果你不確定這個行為的后果,最好是使用默認的參數(shù)( "index.translog.durability": "request" )來避免數(shù)據(jù)丟失站蝠。

五汰具、段合并

由于自動刷新流程每秒會創(chuàng)建一個新的段 ,這樣會導致短時間內(nèi)的段數(shù)量暴增菱魔。而段數(shù)目太多會帶來較大的麻煩留荔。 每一個段都會消耗文件句柄、內(nèi)存和 cpu 運行周期澜倦。更重要的是聚蝶,每個搜索請求都必須輪流檢查每個段杰妓;所以段越多,搜索也就越慢碘勉。

Elasticsearch 通過在后臺進行段合并來解決這個問題巷挥。小的段被合并到大的段,然后這些大的段再被合并到更大的段验靡。

段合并的時候會將那些舊的已刪除文檔從文件系統(tǒng)中清除倍宾。被刪除的文檔(或被更新文檔的舊版本)不會被拷貝到新的大段中。

啟動段合并不需要你做任何事胜嗓。進行索引和搜索時會自動進行高职。

  1. 當索引的時候,刷新(refresh)操作會創(chuàng)建新的段并將段打開以供搜索使用兼蕊。
  2. 合并進程選擇一小部分大小相似的段初厚,并且在后臺將它們合并到更大的段中。這并不會中斷索引和搜索孙技。
image.png
  1. 一旦合并結(jié)束产禾,老的段被刪除
    1)新的段被刷新(flush)到了磁盤。 ** 寫入一個包含新段且排除舊的和較小的段的新提交點牵啦。
    2)新的段被打開用來搜索亚情。
    3)老的段被刪除。


    image.png

合并大的段需要消耗大量的 I/O 和 CPU 資源哈雏,如果任其發(fā)展會影響搜索性能楞件。Elasticsearch在默認情況下會對合并流程進行資源限制,所以搜索仍然 有足夠的資源很好地執(zhí)行裳瘪。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末土浸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子彭羹,更是在濱河造成了極大的恐慌黄伊,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件派殷,死亡現(xiàn)場離奇詭異还最,居然都是意外死亡,警方通過查閱死者的電腦和手機毡惜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門拓轻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人经伙,你說我怎么就攤上這事扶叉。” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵辜梳,是天一觀的道長粱甫。 經(jīng)常有香客問我,道長作瞄,這世上最難降的妖魔是什么茶宵? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮宗挥,結(jié)果婚禮上乌庶,老公的妹妹穿的比我還像新娘。我一直安慰自己契耿,他們只是感情好瞒大,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著搪桂,像睡著了一般透敌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上踢械,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天酗电,我揣著相機與錄音,去河邊找鬼内列。 笑死撵术,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的话瞧。 我是一名探鬼主播嫩与,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼交排!你這毒婦竟也來了划滋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤埃篓,失蹤者是張志新(化名)和其女友劉穎古毛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體都许,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年嫂冻,在試婚紗的時候發(fā)現(xiàn)自己被綠了胶征。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡桨仿,死狀恐怖睛低,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤钱雷,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布骂铁,位于F島的核電站,受9級特大地震影響罩抗,放射性物質(zhì)發(fā)生泄漏拉庵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一套蒂、第九天 我趴在偏房一處隱蔽的房頂上張望钞支。 院中可真熱鬧,春花似錦操刀、人聲如沸烁挟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撼嗓。三九已至,卻和暖如春欢唾,著一層夾襖步出監(jiān)牢的瞬間且警,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工匈辱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留振湾,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓亡脸,卻偏偏與公主長得像押搪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子浅碾,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 使文本可被搜索 最好的支持 一個字段多個值 需求的數(shù)據(jù)結(jié)構(gòu)是我們在 倒排索引 章節(jié)中介紹過的 倒排索引 大州。 倒排索...
    techhow閱讀 1,659評論 0 0
  • 1. 使文檔可被搜索 ?? 傳統(tǒng)的數(shù)據(jù)庫每個字段存儲單個值,但這對全文檢索并不夠垂谢。文本字段中的每個單詞需要被搜索厦画,...
    布魯斯理閱讀 1,002評論 0 0
  • 生活中的數(shù)據(jù) 搜索引擎是對數(shù)據(jù)的檢索,所以我們先從生活中的數(shù)據(jù)說起滥朱。我們生活中的數(shù)據(jù)總體分為兩種: 結(jié)構(gòu)化數(shù)據(jù) 非...
    小蘇c閱讀 605評論 0 0
  • 《本人也在學習中根暑,如果有哪里不對歡迎指出》 介紹 Elasticsearch 是一個分布式可擴展的實時搜索和分析引...
    代碼之神保佑我閱讀 1,162評論 0 0
  • 概要 本篇我們來看看shard內(nèi)部的一些操作原理,了解一下人家是怎么玩的徙邻。 倒排索引 倒排索引的結(jié)構(gòu)排嫌,是非常適合用...
    清茶豆奶閱讀 427評論 0 0