上一篇文章中介紹了Elasticsearch中是如何搜索文本的,同時也簡述了在es裏面索引數據結構的特色不可變性。數據結構
索引不可變性的缺點限制了單個索引存儲的最大數據量以及更新的頻次,因此es面臨的問題是如何解決倒排索引不可更新的特色而同時仍然保持不可變特性帶來的好處。性能
答案就是使用多個索引大數據
代替原來的每次重寫整個索引,es裏面採用方式是增長新的索引來反映最近的變化,而後查詢的時候一次查詢全部的倒排索引,從最先的一直到最新的,而後在合併結果返回。blog
在lucene裏面一個索引是多個segment加上一個commit point文件組成,每一個segment都是一個倒排索引,而commit point這個文件標記了全部的已知的segment文件。以下圖所示:索引
注意lucene裏面的index在es裏面叫作shard,es裏面的一個index能夠包含多個shard,對es裏面的一個索引查詢在es底層會把查詢請求發送到全部shard裏面最後在把結果集合並並返回。內存
回到文章開頭的問題,es如何利用多索引來解決更新的問題,下面咱們看下數據被寫入es的過程:it
(1)當es收到一個寫入或者更新的請求時,首先會把這個數據收集在內存的indexing bufferast
(2)通過必定的間隔或者外部命令觸發時,會在內存緩衝區生成新的segment。file
(3)而後segment首先會被寫到filesystem cache中,這個時候其實搜索就能搜到了。搜索
(4)而後通過一段時間filesystem cache中的segment會被fsync到磁盤文件上並在commit point文件中記錄新segment文件名稱,同時新的segment會被打開確保搜索可見
(5)最終內存裏面buffer區會被清空,並等待收集新的documnet。
以下圖:
當收到查詢請求時,全部的sengment包含內存和磁盤中的會被依次查詢,最終聚合全部segment並準確計算每一個document的相關性,上面的實現方式能夠相對代價比較小的方法處理新增的document。
上面介紹的是新增數據的處理,接下來咱們看下若是有刪除和更新請求那麼es是如何處理的。
首先咱們知道sengments自己是不可變的,因此document是不能從舊的segments中移除,同時也不能被更新,那麼es是如何處理刪除和更新請求的呢?
在每次commit point時,es會生成一個後綴爲.del的文件,這個文件標記了全部已經被刪除的數據,在一條數據被刪除時,es僅僅會在.del文件裏面作個刪除標記,被標記刪除的數據仍然會被查詢到,可是在最終返回結果以前,被標記刪除的數據會被移除,這就是es裏面刪除的實現邏輯。
同理更新的邏輯也相似,當一個document被更新時,舊版本的document也會在.del文件裏面被打上刪除標記,新版本的document會被索引到一個新的segment裏面,這個時候的查詢會同時把二者都查詢出來,但在最終返回結果以前被標記刪除的舊版本數據會被移除掉。
以上就是es裏面實現動態更新索引的內容,在這裏咱們能看到es裏面更新和刪除都相似於採用僞刪除的策略來實現,到這裏你們可能有個疑問,那些被標記刪除的數據,何時纔會被文件系統真正的清除,畢竟量大了仍是對性能有一點影響的,這個在後面segment merge的文章中介紹。