第二章·Elasticsearch內部分片及分片處理機制介紹

1、副本分片介紹

什麼是副本分片?

副本分片的主要目的就是爲了故障轉移,若是持有主分片的節點掛掉了,一個副本分片就會晉升爲主分片的角色。node

在索引寫入時,副本分片作着與主分片相同的工做。新文檔首先被索引進主分片而後再同步到其它全部的副本分片。增長副本數並不會增長索引容量。python

不管如何,副本分片能夠服務於讀請求,若是你的索引也如常見的那樣是偏向查詢使用的,那你能夠經過增長副本的數目來提高查詢性能,但也要爲此,增長額外的硬件資源。linux


Elasticsearch內部分片處理機制

逆向索引shell

與傳統的數據庫不一樣,在Elasticsearch中,每一個字段裏面的每一個單詞都是能夠被搜索的。如teacher:「zls,bgx,lidao,oldboy,alex」咱們在搜索關鍵字oldboy時,全部包含oldboy的文檔都會被匹配到Elasticsearch的這個特性也叫作全文搜索。數據庫

爲了支持這個特性,Elasticsearch中會維護一個叫作「invertedindex」(也叫逆向索引)的表,表內包含了全部文檔中出現的全部單詞,同時記錄了這個單詞在哪一個文檔中出現過。json

例:vim

當前有4個文檔瀏覽器

txt1:「zls,bgx,lidao」
txt2:「zls,oldboy,alex」
txt3:「bgx,lidao,oldboy」
txt4:「oldboy,alex」緩存

那麼Elasticsearch會維護下面一個數據結構表:安全

Term txt1 txt2 txt3 txt4
zls Y Y    
bgx Y   Y  
lidao Y   Y  
oldboy   Y Y Y
alex   Y   Y

隨意搜索任意一個單詞,Elasticsearch只要遍歷一下這個表,就能夠知道有些文檔被匹配到了。

逆向索引裏面不止記錄了單詞與文檔的對應關係,它還維護了不少其餘有用的數據。如:每一個文檔一共包含了多少個單詞,單詞在不一樣文檔中的出現頻率,每一個文檔的長度,全部文檔的總長度等等。這些數據用來給搜索結果進行打分,如搜索zls時,那麼出現zls這個單詞次數最多的文檔會被優先返回,由於它匹配的次數最多,和咱們的搜索條件關聯性最大,所以得分也最多。

逆向索引是不可更改的,一旦它被創建了,裏面的數據就不會再進行更改。這樣作就帶來了如下幾個好處:

  • 1.沒有必要給逆向索引加鎖,由於不容許被更改,只有讀操做,因此就不用考慮多線程致使互斥等問題。

  • 2.索引一旦被加載到了緩存中,大部分訪問操做都是對內存的讀操做,省去了訪問磁盤帶來的io開銷。

  • 3.由於逆向索引的不可變性,全部基於該索引而產生的緩存也不須要更改,由於沒有數據變動。

  • 4.使用逆向索引能夠壓縮數據,減小磁盤io及對內存的消耗。


Segment

既然逆向索引是不可更改的,那麼如何添加新的數據,刪除數據以及更新數據?爲了解決這個問題,lucene將一個大的逆向索引拆分紅了多個小的段segment。每一個segment本質上就是一個逆向索引。在lucene中,同時還會維護一個文件commit point,用來記錄當前全部可用的segment,當咱們在這個commit point上進行搜索時,就至關於在它下面的segment中進行搜索,每一個segment返回本身的搜索結果,而後進行彙總返回給用戶。

引入了segment和commit point的概念以後,數據的更新流程以下圖:

  • 1.新增的文檔首先會被存放在內存的緩存中

  • 2.當文檔數足夠多或者到達必定時間點時,就會對緩存進行commit

    • a. 生成一個新的segment,並寫入磁盤

    • b. 生成一個新的commit point,記錄當前全部可用的segment

    • c. 等待全部數據都已寫入磁盤

  • 3.打開新增的segment,這樣咱們就能夠對新增的文檔進行搜索了

  • 4.清空緩存,準備接收新的文檔

2、Elasticsearch如何合理分配索引分片

爲何要考慮副本分片數量?

大多數ElasticSearch用戶在建立索引時通用會考慮一個重要問題是:我須要建立多少個分片?

分片分配是個很重要的概念, 不少用戶對如何分片都有所疑惑, 固然是爲了讓分配更合理. 在生產環境中, 隨着數據集的增加, 不合理的分配策略可能會給系統的擴展帶來嚴重的問題。

同時, 這方面的文檔介紹也很是少。不少用戶只想要明確的答案而不只僅一個數字範圍, 甚至都不關心隨意的設置可能帶來的問題。

首先,咱們須要瞭解ES中如下幾個名詞,是作什麼的:

集羣(cluster):由一個或多個節點組成, 並經過集羣名稱與其餘集羣進行區分

節點(node):單個ElasticSearch實例. 一般一個節點運行在一個隔離的容器或虛擬機中

索引(index):在ES中, 索引是一組文檔的集合(就是咱們所說的一個日誌)

分片(shard):由於ES是個分佈式的搜索引擎, 因此索引一般都會分解成不一樣部分, 而這些分佈在不一樣節點的數據就是分片. ES自動管理和組織分片, 並在必要的時候對分片數據進行再平衡分配, 因此用戶基本上不用擔憂分片的處理細節,一個分片默認最大文檔數量是20億.

副本(replica):ES默認爲一個索引建立5個主分片, 並分別爲其建立一個副本分片. 也就是說每一個索引都由5個主分片成本, 而每一個主分片都相應的有一個copy.

對於分佈式搜索引擎來講, 分片及副本的分配將是高可用及快速搜索響應的設計核心.主分片與副本都能處理查詢請求, 它們的惟一區別在於只有主分片才能處理索引請求.


謹慎分片

副本對搜索性能很是重要, 同時用戶也可在任什麼時候候添加或刪除副本。額外的副本能給你帶來更大的容量, 更高的呑吐能力及更強的故障恢復能力。

當在ElasticSearch集羣中配置好你的索引後, 你要明白在集羣運行中你沒法調整分片設置。既便之後你發現須要調整分片數量, 你也只能新建建立並對數據進行從新索引(reindex)(雖然reindex會比較耗時, 但至少能保證你不會停機)。

主分片的配置與硬盤分區很相似, 在對一塊空的硬盤空間進行分區時, 會要求用戶先進行數據備份, 而後配置新的分區, 最後把數據寫到新的分區上。

在分片時,主要考慮數據集的增加趨勢,必定要作到不要過分分片,並非分片越多越好,從ES社區用戶對這個熱門主題(分片配置)的分享數據來看, 用戶可能認爲過分分配是個絕對安全的策略(這裏講的過分分配是指對特定數據集, 爲每一個索引分配了超出當前數據量(文檔數)所須要的分片數)。

 

稍有富餘是好的, 但過分分配分片倒是大錯特錯. 具體定義多少分片很難有定論, 取決於用戶的數據量和使用方式. 100個分片, 即使不多使用也多是好的;而2個分片, 即使使用很是頻繁, 也多是多餘的.


咱們要熟知如下幾點內容:
1.每分配一個分片,都會有額外的成本。
2.每一個分片本質上就是一個Lucene索引,所以會消耗相應的文件句柄,內存和CPU資源。
3.每一個搜索請求會調度到索引的每一個分片中。若是分片分散在不一樣的節點卻是問題不太。但當分片開始競爭相同的硬件資源時,性能便會逐步降低。
4.ES使用詞頻統計來計算相關性。固然這些統計也會分配到各個分片上。若是在大量分片上只維護了不多的數據,則將致使最終的文檔相關性較差。


大規模數據集場景

若是真的擔憂數據的快速增加, 咱們建議你多關心這條限制: ElasticSearch推薦的最大JVM堆空間是30~32G, 因此把你的分片最大容量限制爲30GB, 而後再對分片數量作合理估算. 例如, 你認爲你的數據能達到200GB, 咱們推薦你最多分配7到8個分片.

總之, 不要如今就爲你可能在三年後才能達到的10TB數據作過多分配. 若是真到那一天, 你也會很早感知到性能變化的.

儘管本部分並未詳細討論副本分片, 但咱們推薦你保持適度的副本數並隨時可作相應的增長. 若是你正在部署一個新的環境, 也許你能夠參考咱們的基於副本的集羣的設計.這個集羣有三個節點組成, 每一個分片只分配了副本. 不過隨着需求變化, 你能夠輕易的調整副本數量.

對大數據集, 咱們很是鼓勵你爲索引多分配些分片--固然也要在合理範圍內. 上面講到的每一個分片最好不超過30GB的原則依然使用.

不過, 你最好仍是能描述出每一個節點上只放一個索引分片的必要性. 在開始階段, 一個好的方案是根據你的節點數量按照1.5~3倍的原則來建立分片. 例如:若是你有3個節點, 則推薦你建立的分片數最多不超過9(3x3)個.

隨着數據量的增長,若是你經過集羣狀態API發現了問題,或者遭遇了性能退化,則只須要增長額外的節點便可. ES會自動幫你完成分片在不一樣節點上的分佈平衡.

再強調一次, 雖然這裏咱們暫未涉及副本節點的介紹, 但上面的指導原則依然使用: 是否有必要在每一個節點上只分配一個索引的分片. 另外, 若是給每一個分片分配1個副本, 你所需的節點數將加倍. 若是須要爲每一個分片分配2個副本, 則須要3倍的節點數.


總結

再次聲明, 數據分片也是要有相應資源消耗,而且須要持續投入.

當索引擁有較多分片時, 爲了組裝查詢結果, ES必須單獨查詢每一個分片(固然並行的方式)並對結果進行合併. 因此高性能IO設備(SSDs)和多核處理器無疑對分片性能會有巨大幫助. 儘管如此, 你仍是要多關心數據自己的大小,更新頻率以及將來的狀態. 在分片分配上並無絕對的答案, 只但願你們能從本博客中受益.

3、分片操做實戰

分片

正如上文中提到,建立分片,不超過3倍,在本課程中,咱們有兩個節點,因此咱們能夠設置6個分片。

#在每一個節點上執行,分配1個副本6個分片 [root@elkstack01 ~]# curl -XPUT 10.0.0.51:9200/_template/my_template -d' { "template": "*", "settings": { "index": { "number_of_shards": 6, "number_of_replicas": 1 } } }' #返回結果爲true,分片成功 {"acknowledged":true} 

測試提交數據

打開瀏覽器,訪問:http://10.0.0.51:9100/


驗證索引及頁面詳解


主節點和副本節點的區別

主節點的職責:
統計各node節點狀態信息、集羣狀態信息統計、索引的建立和刪除、索引分配的管理、關閉node節點等。

副本節點的職責:
同步數據,等待機會成爲Master(當主節點宕機或者重啓時)。

4、集羣檢測實戰

檢測集羣狀態

在linux中,咱們能夠經過curl命令獲取集羣的狀態.

[root@elkstack02 ~]# curl –sXGET http://10.0.0.51:9200/_cluster/health?pretty=true 

執行結果以下圖所示:
獲取到的是一個json格式的返回值,那就能夠經過python對其中的信息進行分析,例如對status進行分析,若是等於green(綠色)就是運行在正常,等於yellow(黃色)表示副本分片丟失,red(紅色)表示主分片丟失。


python腳本檢測
#編寫python腳本 [root@elkstack01 ~]# vim es_cluster_status.py #!/usr/bin/env python #coding:utf-8 #Author:_DriverZeng_ #Date:2017.02.12 import smtplib from email.mime.text import MIMEText from email.utils import formataddr import subprocess body = "" false = "false" clusterip = "10.0.0.51" obj = subprocess.Popen(("curl -sXGET http://"+clusterip+":9200/_cluster/health?pretty=true"),shell=True, stdout=subprocess.PIPE) data = obj.stdout.read() data1 = eval(data) status = data1.get("status") if status == "green": print "\033[1;32m 集羣運行正常 \033[0m" elif status == "yellow": print "\033[1;33m 副本分片丟失 \033[0m" else: print "\033[1;31m 主分片丟失 \033[0m" #執行結果以下 [root@elkstack01 ~]# python es_cluster_status.py 集羣運行正常
相關文章
相關標籤/搜索