Elastic Stack-Elasticsearch使用介紹(三)

1、前言api

    上一篇說了這篇要講解Search機制,可是在這個以前咱們要明白下文件是怎麼存儲的,咱們先來說文件的存儲而後再來探究機制;緩存

2、文檔存儲
併發

    以前說過文檔是存儲在分片上的,這裏要思考一個問題:文檔是經過什麼方式去分配到分片上的?咱們來思考以下幾種方式:async

    1.經過文檔與分片取模實現,這樣作的好處在於能夠將文檔平均分配到因此的分片上;性能

    2.隨機分配固然也能夠,這種可能形成分配不均,照成空間浪費;日誌

    3.輪詢這種是最不可取的,採用這種你須要創建文檔與分片的映射關係,這樣會致使成本太大;blog

    通過一輪強烈的思考,咱們選擇方案1,沒錯你想對了,這裏Elasticsearch也和咱們思考的是同樣的,咱們來揭露下他分配的公式:排序

    shard_num = hash(_routing)%num_primary_shards索引

    routing是一個關鍵參數,默認是文檔id,能夠自行指定;隊列

    number_of_primary_shard 主分片數;

    以前咱們介紹過節點的類型,接下來咱們來介紹下,當文檔建立時候的流程:

    假設的狀況:1個主節點和2個數據節點,1個副本:

    文檔的建立:

    1.客戶端向節點發起建立文檔的請求;

    2.經過routing計算文檔存儲的分片,查詢集羣確認分片在數據節點1上,而後轉發文檔到數據節點1;

    3.數據節點1接收到請求建立文檔,同時發送請求到該住分片的副本;

    4.主分片的副本接收到請求則開始建立文檔;

    5.副本分片文檔完成之後發送成功的通知給主分片;

    6.當主分片接收到建立完成的信息之後,發送給節點建立成功的通知;

    7.節點返回結果給客戶端;

3、Search機制

    搜索的類型其實有2種:Query Then Ferch和DFS Query Then Ferch,當咱們明白如何存儲文件的是時候,再去理解這兩種查詢方式會很簡單;

    Query Then Ferch

    Search在執行的時候分爲兩個步驟運做Query(查詢)和Fetch(獲取),基本流程以下:

    1.將查詢分配到每一個分片;

    2.找到全部匹配的文檔,並在當前的分片的文檔使用Term/Document Frequency信息進行打分;

    3.構建結果的優先級隊列(排序,分頁等);

    4.將結果的查詢到的數據返回給請求節點。請注意,實際文檔還沒有發送,只是分數;

    5.將全部分片的分數在請求節點上合併和排序,根據查詢條件選擇文檔;

    6.最後從篩選出的文檔所在的各個分片中檢索實際的文檔;

    7.結果將返回給客戶端;

    DFS Query Then Ferch

    DFS是在進行真正的查詢以前, 先把各個分片的詞頻率和文檔頻率收集一下, 而後進行詞搜索的時候, 各分片依據全局的詞頻率和文檔頻率進行搜索和排名,基本流程以下:

    1.提早查詢每一個shard,詢問Term和Document frequency;

    2.將查詢分配到每一個分片;

    3.找到全部匹配到的文檔,而且在全部分片的文檔使用Term/Document Frequency信息進行打分;

    4.構建結果的優先級隊列(排序,分頁等);

    5.將結果的查詢到的數據返回給請求節點。請注意,實際文檔還沒有發送,只是分數;

    6.來自全部分片的分數合併起來,並在請求節點上進行排序,文檔被按照查詢要求進行選擇;

    7.最終,實際文檔從他們各自所在的獨立的分片上檢索出來;

    8.結果被返回給客戶端;

    總結下,根據上面的兩種查詢方式來看的DFS查詢得分明顯會更接近真實的得分,可是DFS 在拿到全部文檔後再重新完整的計算一次相關性算分,耗費更多的cpu和內存,執行性能也比較低下,通常不建議使用。使用方式以下:

    

   另外要是當文檔數據很少的時候能夠考慮使用一個分片;

   這個地方咱們在作一些深刻的思考:咱們搜索的時候是經過倒排索引,可是倒排索引一旦創建是不能修改的,這樣作有那些好處壞處?

   好處:

   1.不用考慮併發寫入文件的問題,杜絕鎖機制帶來的性能問題;

   2.文件再也不更改,能夠充分利用文件系統緩存,只需載入一次,只要內容足夠,對該文件的讀取都會從內存中讀取,性能高;

   壞處:

   寫入新文檔時,必須從新構建倒排索引文件,而後替換老文件後,新文檔才能被檢索,致使文檔實時性差;

   問題:

   對於新插入文檔的時候寫入倒排索引,致使倒排索引重建的問題,假如根據新文檔來從新構建倒排索引文件,而後生成一個新的倒排索引文件,再把用戶的原查詢切掉,切換到新的倒排索引。這樣開銷會很大,會致使實時性很是差。

  

 Elasticsearch如何解決文件搜索的實時性問題:

 

   新文檔直接生成新的倒排索引文件,查詢的時候同時查詢全部的倒排文件,而後作結果的彙總計算便可,ES是是經過Lucene構建的,Lucene就是經過這種方案處理的,咱們介紹下Luncene構建文檔的時候的結構:

   1.Luncene中單個倒排索引稱爲Segment,合在一塊兒稱爲Index,這個Index與Elasticsearch概念是不相同的,Elasticsearch中的每一個Shard對應一個Lucene Index;

   2.Lucene會有個專門文件來記錄全部的Segment信息,稱爲Commit Point,用來維護Segment的信息;

   

   

    Segment寫入磁盤的時候過程當中也是比較慢的,Elasticsearch提供一個Refresh機制,是經過文件緩存的機制實現的,接下咱們介紹這個過程:

    1.在refresh以前的文檔會先存儲在一個Buffer裏面,refresh時將Buffer中的全部文檔清空,並生成Segment;

    2.Elasticsearch默認每1秒執行一次refresh,所以文檔的實時性被提升到1秒,這也是Elasticsearch稱爲近實時(Near Real Time)的緣由;

    Segment寫入磁盤前若是發生了宕機,那麼其中的文檔就沒法恢復了,怎麼處理這個問題?

    Elasticsearch引入translog(事務日誌)機制,translog的寫入也能夠設置,默認是request,每次請求都會寫入磁盤(fsync),這樣就保證全部數據不會丟,但寫入性能會受影響;若是改爲async,則按照配置觸發trangslog寫入磁盤,注意這裏說的只是trangslog自己的寫盤。Elasticsearch啓動時會檢查translog文件,並從中恢復數據;

    還有一種機制flush機制,負責將內存中的segment寫入磁盤和刪除舊的translog文件;

    

    新增的時候搞定了,那刪除和更新怎麼辦?

    刪除的時候,Lucene專門維護一個.del文件,記錄全部已經刪除的文檔,del文件上記錄的是文檔在Lucene內部的id,查詢結果返回前過濾掉.del中的全部文檔;

    更新就簡單了,先刪除而後再建立;

    隨着Segment增長,查詢一次會涉及不少,查詢速度會變慢,Elasticsearch會定時在後臺進行Segment Merge的操做,減小Segment的數量,經過force_merge api能夠手動強制作Segment Merge的操做;

    另外能夠參考下這篇文段合併;

4、下節預告

   原本還想說下聚合、排序方面的查詢,可是看篇幅也差很少了,留點時間出去浪,最近不光要撒狗糧,也要撒知識,國慶節期間準備完成Elastic Stack系列,下面接下來還會有4-5篇左右,歡迎你們加羣438836709,歡迎你們關注我公衆號!

   

相關文章
相關標籤/搜索