Elasticsearch-分佈式日誌搜索

1.elasticsearch底層採用lucenehtml

Lucene底層原理:node

2.Elasticsearch架構圖:git

第1部分分析了Elasticsearch基本的讀、寫、更新、存儲等方面的實現原理,本文檔主要介紹Elasticsearch如何實現分佈式系統的三個特性(consensus, concurrency和consistency),以及分片的內部概念,例如:translog(Write Ahead Log - WAL)和Lucene segments。 
本章主要包括如下內容:github

  • Consensus: 腦裂(split-brain)和quorum機制
  • Concurrency(併發)
  • Consistency(一致性):確保一致的寫入和讀取
  • Translog (Write Ahead Log — WAL)
  • Lucene segments

Consensus(腦裂和quorum機制)

    Consensus是一個分佈式系統的基本挑戰。它要求分佈式系統中的全部的進程/節點,對給定的數據的值/狀態達成一致。有不少Consensus的算法,如RaftPaxos等。這些算法在數學上被證實是有效的,但Elasticsearch實現了它本身的consensus系統(zen discovery),是由於Shay Banon(Elasticsearch的建立者)所描述的緣由。 
    zen discovery模塊有兩個部分:算法

  • Ping:執行該過程的節點,用來發現對方。
  • Unicast:該模塊包含一個主機名列表,用於控制要ping哪一個節點。

    Elasticsearch是一種點對點(peer-to-peer)系統,其中全部節點彼此通訊,而且只有一個活動的主節點,該節點能夠更新和控制羣集狀態和操做。新的Elasticsearch集羣將會進行一次選舉,該選舉做爲ping進程的一部分在節點中運行。在全部有資格選舉的節點中,其中有一個節點被選舉爲主節點(master node),其餘節點加入該主節點。 
    默認的ping_interval爲1秒,ping_timeout爲3秒。當節點加入時,他們會發生一個join的請求給master主機,該請求有一個join_timeout時間,默認是參數ping_timeout的20倍。 
    若主節點失敗,集羣中的幾點再次開始ping,開始另外一次新的選舉。若是節點意外地認爲主節點發生故障,而且經過其餘節點發現主節點,則該ping過程也將有所幫助。 
    注意:默認狀況下,客戶端(client)和數據節點不會對選舉過程作出貢獻。能夠經過改變如下參數的設置,這些參數在elasticsearch.yml 文件中:數據庫

discovery.zen.master_election.filter_client:False
 discovery.zen.master_election.filter_data: False

    故障檢測的過程是這樣的:主節點ping全部的節點來檢查這些節點是否存活,而全部的節點回ping主節點來彙報他們是存活的。緩存

    若使用默認配置,Elasticsearch會遇到腦裂的問題,若是是網絡分區,則節點能夠認爲主節點已經死機,並將其自身選爲主節點,從而致使集羣具備多個主節點。這樣可能致使數據丟失,可能沒法正確合併數據。這種狀況能夠經過將如下屬性設置爲主合格節點的法定數量來避免:網絡

discovery.zen.minimum_master_nodes = int(# of master eligible nodes/2)+1

這裏寫圖片描述

    該參數要求法定數量的可參加選舉的節點加入新的選舉過程來完成新的選舉過程,並接受新節點做爲新的master節點。這是確保集羣穩定性的極其重要的參數,若是集羣大小發生變化,能夠進行動態更新。圖a和b分別顯示了在minimum_master_nodes屬性被設置,和未被設置的兩種狀況。 
    注意:對於生產環境的集羣,建議有3個專用主節點,在任何給定的時間點只有一個處於活動狀態,其餘的節點不服務任何客戶請求。架構

Concurrency(併發控制)

    Elasticsearch是一個分佈式系統,支持併發請求。當建立/更新/刪除請求命中主分片時,它同時發送到副本分片,可是這些請求到達的順序是不肯定的。在這種狀況下,Elasticsearch使用樂觀併發控制(optimistic concurrency control)來確保文檔的較新版本不會被舊版本覆蓋。 
    每一個被索引的文檔都會有一個版本號,每次文檔改變時,該版本號就會增長。使用版本號能夠確保對文檔的改變是順序進行的。爲確保咱們的應用程序中的更新不會致使數據丟失,Elasticsearch的API容許您指定,更改應該應用到目前哪個版本號。若是請求中指定的版本號,早於分片中存在的版本號,則請求失敗,這意味着該文檔已被其餘進程更新。 
    如何處理失敗的請求?能夠在應用程序級別進行控制。還有其餘鎖定選項可用,您能夠在這裏閱讀併發

    當咱們向Elasticsearch發送併發請求時,下一個問題是 - 咱們如何使這些請求保持一致?如今要回答 CAP原則,還不是太清晰,這是接下來要討論的問題。 
這裏寫圖片描述 
可是,咱們將回顧如何使用Elasticsearch實現一致的寫入和讀取。

Consistency (確保一致的寫和讀)

    對於寫操做,Elasticsearch支持與大多數其餘數據庫不一樣的一致性級別,它容許初步檢查以查看有多少個分片可用於容許寫入。可用的選項是:quorum的可設置的值爲:one和all。默認狀況下,它被設置爲:quorum,這意味着只有當大多數分片可用時,才容許寫入操做。在大部分分片可用的狀況下,因爲某種緣由,寫入複製副本分片失敗仍然可能發生,在這種狀況下,副本被認爲是錯誤的,該分片將在不一樣的節點上進行重建。

    對於讀操做,新文檔在刷新間隔時間後才能用於搜索。爲了確保搜索結果來自最新版本的文檔,能夠將複製(replication)設置爲sync(默認值),當在主分片和副本分片的寫操做都完成後,寫操做才返回。在這種狀況下,來自任何分片的搜索請求將從文檔的最新版本返回結果。 
    即便你的應用程序爲了更快的indexing而設置:replication=async,也可使用_preference參數,能夠爲了搜素請求把它設置爲primary。這樣,查詢主要分片就是搜索請求,並確保結果未來自最新版本的文檔。 
    當咱們瞭解Elasticsearch如何處理consensus,併發性和一致性時,咱們來看看分片內部的一些重要概念,這些概念致使了Elasticsearch做爲分佈式搜索引擎的某些特徵

Translog

    自從開發關係數據庫以來,數據庫世界中一直存在着write ahead log(WAL)或事務日誌(translog)的概念。Translog在發生故障的狀況下確保數據的完整性,其基本原則是,在數據的實際更改提交到磁盤以前必須先記錄並提交預期的更改。 
    當新文檔被索引或舊文檔被更新時,Lucene索引會更改,這些更改將被提交到磁盤以進行持久化。每次寫請求以後進行持久化操做是一個很是消耗性能的操做,它經過一次持久化多個修改到磁盤的方式運行(譯註:也就是批量寫入)。正如咱們在以前的一篇博客中描述的那樣,默認狀況下每30分鐘執行一次flush操做(Lucene commit),或者當translog變得太大(默認爲512MB)時)。在這種狀況下,有可能失去兩次Lucene提交之間的全部變化。爲了不這個問題,Elasticsearch使用translog。全部的索引/刪除/更新操做都先被寫入translog,而且在每一個索引/刪除/更新操做以後(或者每默認默認爲5秒),translog都被fsync’s,以確保更改被持久化。在主文件和副本分片上的translog被fsync’ed後,客戶端都會收到寫入確認。

    在兩次Lucene提交或從新啓動之間出現硬件故障的狀況下,會在最後一次Lucene提交以前重播Translog以從任何丟失的更改中恢復,並將全部更改應用於索引。 
    建議在從新啓動Elasticsearch實例以前顯式刷新translog,由於啓動將更快,由於要重播的translog將爲空。POST / _all / _flush命令可用於刷新集羣中的全部索引。 
使用translog刷新操做,文件系統緩存中的段將提交到磁盤,以使索引持續更改。 
    如今咱們來看看Lucene segment:

Lucene Segments

    Lucene索引由多個片斷(segment)組成,片斷自己是徹底功能的倒排索引。片斷是不可變的,這容許Lucene增量地向索引添加新文檔,而無需從頭開始重建索引。對於每一個搜索請求,搜全部段都會被搜素,每一個段消耗CPU週期,文件句柄和內存。這意味着分段數越多,搜索性能就越低。 
    爲了解決這個問題,Elasticsearch將小段合併成一個更大的段(以下圖所示),將新的合併段提交到磁盤,並刪除舊的較小的段。 
這裏寫圖片描述  合併操做將會自動發生在後臺,而不會中斷索引或搜索。因爲分段合併可能會浪費資源並影響搜索性能,所以Elasticsearch會限制合併過程的資源使用,以得到足夠的資源進行搜索。

相關文章
相關標籤/搜索