Elasticsearch 架構設計及說明 Elasticsearch 架構設計及說明

Elasticsearch 架構設計及說明

Elasticsearch 架構層:

Elasticsearch 五層架構設計圖:

說明:

  • Elasticsearch是基於Lucene架構實現的,所以其核心層爲Lucene
  • Elasticsearch 目前支持HTTPThriftMemcache三種協議,默認是HTTP
  • JMX指在Elasticsearch中對 Java 的管理架構,用來管理Elasticsearch應用

一、節點自動發現機制

  • 在進行Elasticsearch 分佈式安裝過程中,我們通過在elasticsearch.yml文件中配置 ‘cluster.name’就能將不同的節點連接到同一個
    集羣中,正是使用了Elasticsearch的節點發現機制。Elasticsearch內置有默認發現模塊,同時也支持插件方式的發現機制。
  • 發現機制用於發現集羣中的節點和選舉主節點(master節點)

Elasticsearch內嵌自動發現機制

  • Azure discovery 插件方式:多播模式
  • EC2 discovery 插件方式:多播模式
  • Google Compute Engine discovery 插件方式:多播模式
  • **Zen Discovery **:默認實現方式,支持多播模式和單播模式。提供了單播模式和基於文件的發現,並且可以擴展爲通過插件支持其他形式的發現機制。

單播模式和多播模式配置參數

  • discovery.zen.ping.multicast.enabled:表示關閉多播模式的自動發現機制,主要爲了防止其他機器上的節點自動接入。
  • discovery.zen.fd.ping_timeoutdiscovery.zen.ping.timeout:表示設置了節點和節點之間連接ping命令執行的超時時長。
  • discovery.zen.minimum_master_nodes:表示集羣中選舉主節點時至少需要有多少個節點參與
  • discovery.zen.ping.unicast.hosts:表示在單播模式下,節點應該自動發現哪些節點列表
  • action_create_indexfalse表示關閉自動創建索引

如:

discovery.zen.ping.multicast.enabled:true
discovery.zen.fd.ping_timeout:100s
discovery.zen.ping.timeou:100s
discovery.zen.minimum_master_nodes:2
discovery.zen.ping.unicast.hosts:['192.168.x1.y1:9300','192.168.x2.y2:9300']
action_create_index:false

1、單播模式

* Elasticsearch支持同一臺主機啓動多個節點,所以只有在同一臺機器上運行的節點纔會自動組成集羣。
* 單播模式下,需要配置Elasticsearch,填寫集羣中的IP地址列表。如下:
discovery.zen.ping.unicast.hosts:['192.168.x1.y1:9300','192.168.x2.y2:9300']

單播模式下的配置信息

discovery.zen.ping.multicast.enabled:false
discovery.zen.fd.ping_timeout:100s
discovery.zen.ping.timeou:100s
discovery.zen.minimum_master_nodes:2
discovery.zen.ping.unicast.hosts:['192.168.x1.y1:9300','192.168.x2.y2:9300']

集羣構建及主節點選舉過程:

  1. 節點啓動後執行ping命令(RPC命令),如果discovery.zen.ping.unicast.hosts中有設置,則ping設置hosts中,否則嘗試ping localhost的幾個端口。最後返回包含節點的基本信息以及該節點認爲的主節點。
  2. 從各個節點認爲的master中,按照ID的字典排序選取第一個爲主節點。如果各個節點沒有認爲的master,則從各個節點中按照ID字典排序選取第一個作爲主節點。

注:

  • 在選舉主節點時,如果節點數達不到最小值得限制(discovery.zen.minimum_master_nodes:num),則循環集羣構建與主節點選舉過程,直到節點數超過最小限制值,纔可以開始選舉主節點。
  • 如果只有一個本地節點,則主節點就是它自己。
  • 如果當前節點是主節點了,則需要等到節點數達到限制值,再提供服務
  • 如果當前節點不是主節點,則嘗試加入主節點所在的集羣

2、多播模式

  • 多播模式下,只需在每個節點配置好集羣名稱和節點名稱即可。互相通信的節點會更加Elasticsearch自定義的服務發現協議,按照多播的方式
    尋找網絡上配置在同樣集羣內的節點。
  • 【注】雖然Elasticsearch支持多播和單播模式兩種自動節點發現機制,但是多播模式安全性不高,已經不被多大數操作系統支持。目前
    Elasticsearch默認發現機制爲單播模式,以防止節點無意中加入集羣。所以是配置中需要將多播模式關閉,如下:
discovery.zen.ping.multicast.enabled: false 

二、節點類型

節點角色在配置文件(/config)elasticsearch.yml文件中設置即可,如下:

# 是否爲候選主節點
node.master:true
# 是否爲數據節點
node.data:true

三、分片和路由

由於Elasticsearch中,在一個多分片的索引中寫入數據時,需要通過路由來確定具體陷入哪一個分片中,所以在創建索引時需要指定分片數量,
配置副本,並且分片的數量一旦確定就不能修改。

1、分片

通過配置創建索引時的Setting來配置分片和副本數量,如下:

index.number_of_shards:5
index.number_of_replicas:1

補充說明:

  • 對文檔的新建、索引和刪除請求等寫操作,必須在主分片上面完成之後才能被複制到副本分片。
  • Elasticsearch 使用樂觀鎖來控制加快寫入速度的併發寫入引起的數據衝突問題,通過爲每個文檔設置一個version(版本號),當文檔被修改時版本號遞增來實現。
  • 當向Elasticsearch寫入數據時,Elasticsearch根據文檔標識符ID將文檔分配到多個分片上,當查詢數據時,Elasticsearch會查詢所有的分片並彙總結果。
  • 對於分片,用戶並不知道數據存在哪個分片上。

2、路由

爲了避免查詢時部分分片查詢失敗影響結果的準確性,Elasticsearch引入了路由功能。
當數據寫入時,通過路由將數據寫入指定分片;
當查詢數據時,通過相同的路由指明在哪個分片將數據查出來

索引數據分片算法:

shard_num = hash(_routing) % num_primary_shards  #_routing默認爲id字段或者parent字段

補充說明:

  • 通過 Hash 分片來保證在每個分片上的數據量能均勻分佈,避免各個分片的存儲負載不均衡
  • 在做數據檢索時,Elasticsearch默認會搜索所有分片上的數據,最後再主節點上彙總各個分片數據並排序處理,返回最終的結果數據。

四、Elasticsearch 數據寫入過程

數據存儲路徑配置:(/config)elasticsearch.yml文件中

path.data:/path/to/data # 索引數據
path.logs:/path/to/logs # 日誌數據

【注】不建議使用默認值,防止升級Elasticsearch而導致數據部分甚至全部丟失

1、分段存儲

  • 在索引中,索引文件被拆分爲多個子文件,其中每個子文件就叫做段,且每個段都是一個倒排索引的小單元
  • 索引數據在磁盤中是以分段形式存儲的
  • 段具有不可變性,一旦索引的數據被寫入硬盤,就不能在修改

我們可以思考一下,爲什麼Elasticsearch中數據的存儲要引入段?

  • 如果熟悉CurrentHashMap原理的,可以想到其中的緣由,引入段就是爲了減少鎖的使用,提高併發。
  • 假設我們將全部文檔集合構建在一個很大的倒排索引文件中,且數據還在不斷增加,那麼當我們進行修改時,就需要全量更新當前的倒排索引文件
    這樣就使得數據更新變得時效性很差,且耗費大量資源。
  • 引入段的存儲模式,避免了在讀寫操作時使用鎖,從而大大提升Elasticsearch的讀寫性能。

當段被寫入磁盤後會生成一個提交點,並生成一個用來記錄所有段信息的文件,則對於該文件段只有讀的權限,永遠失去寫的權限。同時該部分數據可以被 Elasticsearch 用戶檢索到。而當段還在內存中時,此時分段只擁有寫的權限,數據還能不斷寫入,但不具備讀數據的權限,且無法被 Elasticsearch 用戶檢索到。

如果段一旦提交不能再寫,那麼我們如何進行 ’‘ (新增、更新和刪除)的操作呢?

在面對段的不可修改特性,Elasticsearch採用不將文檔從舊段中移除,而是新增一個.del文件,記錄被 '改' 文檔的段信息。
當用戶檢索時,文檔依然可以被查詢到,但他會在最終結果被返回前通過.del文件將其從結果集中移除。
如當更新數據時,會先創建一個段,然後將更新好的數據寫入新段中,生成提交點,再在.del文件中標記舊段,從而達到更新的效果。

段的優缺點:

  • 優點:不需要鎖,大大提升了 Elasticsearch 的讀寫性能
  • 缺點1:存儲空間佔用大,如當刪除舊數據時,舊數據不會被馬上刪除,而是在.del文件中標記爲刪除,只有等到段更新時才被移除。這就導致了存儲空間的浪費,倘若頻繁更新數據,則每次更新都是新增新的數據到新分段,並標記舊的分段中的數據,存儲空間的浪費會更多。
  • 缺點2:在檢索數據時,檢索得到的數據集中包含所有的結果集,因此主節點需要排除被標記刪除的舊數據,進而增加了查詢負擔。

2、延遲寫策略

Elasticsearch中,索引寫入磁盤是異步寫入的。爲了提升寫的性能,延遲寫策略採用了 '延遲寫策略' 來解決新增一條數據就添加一個段到磁盤上的問題。

延遲寫策略執行過程:

補充說明

  • JVM內存中的數據不以段形式存儲,無法提供檢索功能

  • 當生成段後便可以提供檢索功能,無需等到刷新到磁盤。

  • 刷新除了自動刷新,開發人員可以手動觸發刷新

  • 可通過在創建索引時的Setting文件中配置 refresh_interval的值,來調整索引的刷新頻率。如

    refresh_interval = number 時間單位  # 設置值時需要注意帶上時間單位,否則默認爲ms(毫秒)
    refresh_interval = -1 # 表示關閉索引的自動刷新
    

延遲寫策略優缺點:

  • 優點:減少數據往磁盤上寫的次數,提升Elasticsearch的整體寫入能力
  • 缺點:引入數據丟失風險,如機器斷電等。

爲了解決延遲寫策略引入的數據丟失風險,Elasticsearch又引入了 事務日誌(Translog)機制,用於記錄所有還沒有持久化到磁盤的數據。

添加事務日誌機制後的數據寫入索引流程:

  1. 新文檔被索引之後,先被寫入內存中。爲了防止數據丟失,Elasticsearch會追加一份數據到事務日誌中。
  2. 新的文檔持續在被寫入內存時,同時也會記錄到事務日誌中。此時,新數據不能被檢索和查詢
  3. 當達到默認的刷新時間或內存中的數據達到一定量後,觸發一次Refresh刷新將內存中的數據以一個新段格式刷新到文件緩存系統中,並清空內存。(形成段,可提供檢索和查詢,且不可修改)
  4. 隨着新文檔索引不斷寫入,當日志數據大小超過某個值(512MB),或者超過一定時間(30min)時,觸發一次Flush,此時文件緩存系統中的數據通過Fsync刷新到磁盤中,生成提交點。同時刪除日誌文件,並創建一個空的新日誌文件。

3、段合併

  • ElasticSearch自動刷新階段,每秒都會創建一個新段。因此,極短時間內會產生大量段,消耗較大的資源,如文件句柄、內存和CPU。
  • 檢索階段,由於搜索要求檢查到每個段,然後合併查詢結果,因此段越多,搜索速度越慢。

爲了解決段增多的問題,Elasticsearch引入了段合併機制,定期將較小的段合併到較大的段中,而較大的段合併到更大的段中;

說明:

  • 在段合併過程中,Elasticsearch會將舊的\已刪除的文件從文件系統中清除,從而保證舊的\刪除的文檔不會被拷貝到新的大段中;
  • 段合併機制是自動進行索引和搜索的,它們會選擇一小部分大小相似的段,在後臺將它們合併到更大的段中。
  • 合併的段可以是未提交的,也可以是已提交的。
  • 合併結束後,老的段會被刪除,新段被Refresh到磁盤,同時寫入一個包含新段且排除舊的和較小段的新提交點。
  • 由於段合併需要很大的計算量,因此,Elasticsearch在默認情況下會對段合併流程進行資源限制。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章