elasticsearch學習筆記(三十六)——Elasticsearch 內核原理

倒排索引組成結構以及索引不可變緣由

對於倒排索引是很是適合用來進行搜索的
它的結構:
(1)包含這個關鍵詞的document list
(2)包含這個關鍵詞的全部document的數量:IDF(inverse document frequency)
(3)這個關鍵詞在每一個document中出現的次數:TF(term frequency)
(4)這個關鍵詞在這個document中的次序
(5)每一個document的長度:length norm
(6)包含這個關鍵詞的全部document的平均長度
其實本質上主要是爲了計算相關度分數數據庫

_score = boost * idf * tf 
此時boost = 2.2, idf = 0.18232156, tf = 0.5116279

idf = log(1 + (N - n + 0.5) / (n + 0.5))
此時n = 2 (n, number of documents containing term), 
N = 2(N, total number of documents with field)

tf = freq / (freq + k1 * (1 - b + b * dl / avgdl))
此時freq = 1(freq, occurrences of term within document), 
k1 = 1.2(k1, term saturation parameter), 
b = 0.75(b, length normalization parameter), 
d1 = 4 (dl, length of field), 
avgdl = 5.5(avgdl, average length of field)

倒排索引的不可變好處

(1)不須要鎖,提高了併發能力,避免鎖的問題
(2)數據不變,一直保存在OS cache中,只要cache內存足夠
(3)filter cache一直駐留在內存
(4)能夠壓縮,節省cpu和io開銷
這個對應的就是primary shard的數量不變,不能修改field的屬性(將date改爲text)緩存

倒排索引不可變的壞處

(1)每次都須要從新構建整個索引安全

document寫入原理

(1)數據寫入buffer
(2)commit point
(3)buffer中的數據寫入新的index segment
(4)等待在OS cache中的index segment被fsync強制刷到磁盤上
(5)新的index segment被打開,供search使用
(6)buffer被清空服務器

下面作幾點說明:

一、在Elasticsearch中,底層用的是lucene,lucene底層的index是分爲多個segment的,每一個segment都會存放部分數據。
二、若是是刪除操做,每次commit的時候,就會生成一個.del文件,標明哪一個index segment的哪一個document被刪除了。
三、若是是更新操做,其實是將的doc標記爲deleted,而後將新的document寫入新的index segment中。下次search過來的時候,也許會匹配到一個document的多個版本,可是以前的版本已經被標記爲deleted了,因此只會返回最新版本的doc
四、若是搜索請求過來,在index segment中,匹配到了id=1的doc,此時會發如今.del文件中已經被標識爲deleted了,這種數據就會被過濾掉,不會做爲搜索結果返回。
圖示以下:
圖片描述併發

寫入流程近實時NRT

現有的流程的問題,每次都必須等待fsync將segment刷入磁盤,才能將segment打開供search使用,這樣的話,從一個document寫入,到它能夠被搜索,可能會超過1分鐘,這也就不是近實時的搜索了。主要的瓶頸在於fsync從磁盤IO寫數據進磁盤是很耗時的。
ES寫入流程的改進:
(1)數據寫入buffer
(2)每一個必定時間,buffer中的數據被寫入segment文件,可是先寫入OS cache
(3)只要segment寫入OS cache,那就直接打開供search使用,不當即執行commit
數據寫入OS cache,並被打開供搜索的過程,叫作refresh,默認是每隔一秒refresh一次,也就是說,每隔一秒就會將buffer中的數據寫入OS cache中,寫入一個新的index segment file。因此ES是近實時的,數據寫入到能夠被搜索,默認是1秒。
通常不用修改,讓ES本身搞定就行了,要修改的話,經過refresh_interval參數便可
格式:async

PUT /{index}
{
  "settings": {
    "refresh_interval": "1s"
  }
}

圖示以下:
圖片描述spa

寫入流程的實現 durability可靠存儲

最終流程:

(1)數據寫入buffer緩存和translog日誌文件
(2)每隔一秒,buffer中的數據被寫入新的segment file,並進入os cache,此時segment被打開並供search使用
(3)buffer被清空
(4)重複1~3,新的segment不斷添加,buffer不斷被清空,而translog中的數據不斷累加
(5)當translog長度達到必定程度的時候,commit操做發生
    (5.1)buffer中的全部數據,寫入一個新的segment,並寫入os cache,打開供使用
    (5.2)buffer被清空
    (5.3)一個commit point被寫入磁盤,標明瞭全部的index segment
    (5.4)filesystem cache中的全部index segment file緩存數據,被fsync強制刷到磁盤上
    (5.5)現有的translog被清空,建立一個新的translog

translog

對Lucene的更改僅在Lucene提交期間持久保存到磁盤,這是一項相對昂貴的操做,所以沒法在每次索引或刪除操做後執行。若是進程退出或硬件發生故障,Lucene將在一次提交以後和另外一次提交以前發生的更改將從索引中刪除。日誌

由於Lucene提交對於每一個單獨的更改都執行起來太昂貴,因此每一個分片副本還有一個事務日誌,稱爲與之關聯的translog。全部索引和刪除操做在由內部Lucene索引處理以後但在確認以前寫入translog。在發生崩潰的狀況下,最新的已確認但還沒有包含在上一個Lucene提交中的事務能夠在分片恢復時從translog中恢復。code

Elasticsearch flush是執行Lucene提交併啓動新的translog的過程。在後臺自動執行刷新以確保translog不會變得太大,這將使得在恢復期間重放其操做須要至關長的時間。手動執行刷新的能力也經過API公開,儘管不多須要。orm

translog設置

translog中的數據僅在fsync編輯和提交translog時持久保存到磁盤 。若是發生硬件故障,自上次translog提交以來寫入的任何數據都將丟失。

默認狀況下,fsync若是index.translog.durability設置爲async或request 在每一個索引,刪除, 更新或 批量請求結束時設置爲(默認),則Elasticsearch會每隔5秒提交一次translog 。更確切地說,若是設置爲request,則fsync在主數據庫和每一個已分配的副本服務器上成功編輯和提交translog以後,Elasticsearch將僅向客戶端報告索引,刪除,更新或批量請求的成功 。

如下可動態更新的每索引設置控制translog的行爲:

index.translog.sync_interval
    fsync不管寫入操做 如何,translog都常常被寫入磁盤並提交。默認爲5s。小於的值100ms是不容許的。
index.translog.durability
    是否fsync在每一個索引,刪除,更新或批量請求以後提交translog。此設置接受如下參數:
        request
        (默認)fsync並在每一個請求後提交。若是發生硬件故障,全部已確認的寫入都已提交到磁盤。
        async
        fsync並在每一個背景中提交sync_interval。若是發生硬件故障,將丟棄自上次自動提交以來的全部已確認寫入。
index.translog.flush_threshold_size
    translog存儲還沒有安全保存在Lucene中的全部操做(即,不是Lucene提交點的一部分)。儘管這些操做可用於
    讀取,但若是要關閉而且必須恢復,則須要從新編制索引。此設置控制這些操做的最大總大小,以防止恢復時間
    過長。達到最大大小後,將發生刷新,生成新的Lucene提交點。默認爲512mb。
index.translog.retention.size
    要保留的translog文件的總大小。保留更多的translog文件會增長在恢復副本時執行基於同步操做的機會。如
    果translog文件不足,副本恢復將回退到基於文件的同步。默認爲512mb
index.translog.retention.age
    保留translog文件的最長持續時間。默認爲12h。

圖示以下:
圖片描述

數據恢復

假設os cache中囤積了一些數據,可是此時不巧,宕機了,os cache中的數據所有丟失,那麼咱們怎麼進行數據恢復呢?
咱們知道寫doc的時候也會寫入translog,那麼translog就存儲了上一次flush直到如今最近的數據變動記錄。機器被重啓以後,disk上的數據並無丟失,此時就會將translog文件中的變動記錄進行回收,從新執行以前的各類操做,在buffer中執行,在從新刷一個一個的segment到os cache中,等待下一次commit發生便可。

海量磁盤文件的合併

每秒一個segment file,會致使文件過多,並且每次search都要搜索全部的segment,很耗時。因此在Elasticsearch內部會默認在後臺執行segment merge操做(forcemerge),在merge的時候,被標記爲deleted的document也會被完全物理刪除掉。每次merge的操做流程:(1)選擇一些有類似大小的segment,merge成一個大的segment(2)將新的segment flush到磁盤上去(3)寫一個新的commit point,包括了新的segment,而且排除舊的那些segment(4)將新的segment打開供搜索(5)將舊的segment刪除

相關文章
相關標籤/搜索