當前位置:首頁 » 服務存儲 » es進行fst堆外存儲
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

es進行fst堆外存儲

發布時間: 2022-10-20 08:31:36

1. ElasticSearch部署架構和容量規劃

前面介紹了ElasticSearch原理和使用相關的內容,在生產環境如何比較科學的進行容量規劃、部署、調優、排查問題呢,業界和官方也對相關的問題進行總結,我這邊也結合自己的經驗對這些使用ElasticSearch經常遇到的問題進行了總結。其中主要包括以下三大模塊:

ElasticSearch有多種類型的節點,在前面概述和核心也已經介紹過了。在這里可以重新回顧下。ElasticSearch的部署節點類型如下:

主節點及其候選節點,負責集群狀態(cluster state)的管理

配置項:node.master,默認為true

數據節點,負責數據存儲及處理客戶端請求

配置項:node.data,默認為true

ingest節點,負責數據處理,腳本執行

配置項:node.ingest,默認為true

協調節點

配置項:設置上面三個參數全部為false,那麼它就是一個純協調節點

機器學習節點,收費屬於x-pack

在生產環境部署推薦配置整體思路就是:盡量是一個節點只承擔一個角色。

因為不同的節點所需要的計算機資源都不一樣。職責分離後可以按需擴展互不影響。

資源要求:中高CPU;中高內存;中低磁碟

一般在生產環境中配置3台

一個集群只有1台活躍的主節點,負責分片管理,索引創建,集群管理等操作

資源要求:CPU、內存、磁碟要求都高

資源要求:高配置CPU;中等配置的RAM;低配置的磁碟

資源要求:一般中高CPU;中高內存;低磁碟

協調節點扮演者負載均衡、結果的聚合,在大型的es集群中條件允許可以使用高配的cpu和內存。因為如果客戶端發起了深度分頁等請求可能會導致oom,這個在之前也有過分析。

注意:

如果和數據節點或者Coordinate節點混合部署,數據節點本來相對有比較大的內存佔用。

而Coordinate節點有時候可能會有開銷很高的查詢導致OOM,這些甚至都有可能影響Master節點,導致集群的不穩定。

搭建一個es集群是由模式可循的。

這是一個基礎版的職責分離的部署架構:

但是如果大量的聚合查詢等操作,這種架構不太適合了。

當系統中有大量的復雜查詢或者聚合時候,我們可增加Coordinating節點,增加查詢的性能,這里增加了負載均衡層,通過負載均衡擴展時應用程序無感知。

這樣部署部署相互影響,寫入多的話,多部署ingetst節點,讀的時候聚合查詢較多可以多部署協調節點,存儲數據量大,可以適當對數據節點進行調優。

我們知道數據有冷熱之分,比如寫入頻繁的日誌數據,近期的索引將會頻繁寫入。es根據數據這些特徵引入了hot節點和warm節點。

使用ssd,該節點上的索引不斷的有新文檔寫入和查詢,對cpu、io的要求較高。

可以使用HDD,上面的索引不會有寫入,查詢較少。上面只保存只讀索引或者舊索引,使用大容量便宜的機械硬碟

配置步驟:

針對多機房災備,ElasticSearch業界有多種不同的通用解決方案:

一個集群中的節點分布在不同的機房

應用程序同時將數據寫入兩個集群

應用程序先將數據寫入消息隊列,然後由下游的消費者消費並寫入集群

ElasticSearch官方的跨集群復制功能,基於文檔操作實現訂閱復制

定期將索引備份到外部存儲,如hdfs等設備

寫請求交給網關,網關實時寫入主集群,然後非同步寫備集群

如下是基於CCR跨集群復制的部署架構,因為篇幅有限,異地多活又是一個很大的話題,其它方案和其細節可以查閱相關資料。

我們知道當es集群的節點數大於索引的分片數時,集群將無法通過水平擴展提升集群的性能。而分片數過多,對於聚合查詢以及集群的元數據管理也都有影響。我們可以總結為:

分片數量較多

優點:

缺點:

通常建議一個集群總分片數小於10w。

如何設計分片的數量呢?一個分片保持多大的數據量比較合適呢?

我們需要根據使用場景來設置:

避免使用非常大的分片,因為這會對群集從故障中恢復的能力產生負面影響。而每個分片也會消耗相應的文件句柄,內存和CPU資源,分片太多會互相競爭,影響性能。

主分片數一旦確定就無法更改,只能新建創建並對數據進行重新索引(reindex),雖然reindex會比較耗時,但至少能保證你不會停機。所以我們一定要科學的設計分片數。

這里摘錄於官方關於分片大小的建議:

主分片與副本都能處理查詢請求,它們的唯一區別在於只有主分片才能處理索引請求。副本對搜索性能非常重要,同時用戶也可在任何時候添加或刪除副本。額外的副本能給帶來更大的容量,更高的呑吐能力及更強的故障恢復能力

3.1.3. 小結

根據實際經驗我們稍微總結下:

對於數據量較小(100GB以下)的index

對於數據量較大(100GB以上)的index:

綜合考慮整個index的shard數量,如果shard數量(不包括副本)超過50個,就很可能引發拒絕率上升的問題,此時可考慮把該index拆分為多個獨立的index,分攤數據量,同時配合routing使用,降低每個查詢需要訪問的shard數量。

關閉交換分區的方法是:

這里是官方的jvm推薦配置鏈接:

https://www.elastic.co/cn/blog/a-heap-of-trouble

es的節點提供查詢的時候使用較多的內存來存儲查詢緩存,es的lucene寫入到磁碟也會先緩存在內存中,我們開啟設計這個es節點時需要根據每個節點的存儲數據量來進行判斷。這里有一個流行的推薦比例配置:

示例:

有一個業務的數據量預估實際有1T,我們把副本設置1個,那麼es中總數據量為2T。

這里31G表示的是jvm設置不超過32g否則不會使用java的指針壓縮優化了。

前面也提到過,數據節點推薦使用ssd

可以考慮:

寫入的目標在於增大寫入的吞吐量,這里主要從兩個方面進行優化:

這里可以針對myindex索引優化的示例:

首先有幾個原則我們需要清楚:

我們可以通過health相關的api進行查看

我們可以使用profile api來定位慢查詢。

在查詢條件中設置profile為true的參數,將會顯示查詢經歷的細節。

其結果為:

這里會返回一個shards列表。其中:

主要包含了如下信息:

Profile API讓我們清楚地看到查詢耗時。提供了有關子查詢的詳細信息,我們可以清楚地知道在哪個環節查詢慢,另外返回的結果中,關於Lucene的詳細信息也讓我們深入了解到ES是如何執行查詢的。

ES記錄了兩類慢日誌:

慢搜索日誌

用來記錄哪些查詢比較慢,每個節點可以設置不同的閾值。

之前我們已經詳細分析了ES的搜索由兩個階段組成:

慢搜索日誌給出了每個階段所花費的時間和整個查詢內容本身。慢搜索日誌可以為查詢和取回階段單獨設置以時間為單位的閾值,在定義好每個級別的時間後,通過level決定輸出哪個級別的日誌。

示例如下

前面參考官方鏈接:

https://www.elastic.co/guide/en/elasticsearch/reference/7.17/index-moles-slowlog.html

如果出現節點佔用CPU很高,我們需要知道CPU在運行什麼任務,一般通過線程堆棧來查看。

這里有兩種方式可以查看哪些線程CPU佔用率比較高:

這里推薦使用hot_threads api

通過返回的結果可以看到什麼線程佔用更高,正在做什麼操作。更詳細的內容可以參考官網:

https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-nodes-hot-threads.html

4.3.2 內存使用率過高

1)緩存類型

首先我們需要了解ES中的緩存類型,緩存主要分成如圖所示三大類,如下圖所示,一個es節點的內存結構:

Node Query Cache(Filter Context)

Shard Query Cache(Cache Query的結果)

Fielddata Cache

Segments Cache

(segments FST數據的緩存),為了加速查詢,FST永駐堆內內存,無法被GC回收。該部分內存無法設置大小,長期佔用50%~70%的堆內存,只能通過delete index,close index以及force-merge index釋放內存

ES底層存儲採用Lucene(搜索引擎),寫入時會根據原始數據的內容,分詞,然後生成倒排索引。查詢時,先通過查詢倒排索引找到數據地址(DocID)),再讀取原始數據(行存數據、列存數據)。

但由於Lucene會為原始數據中的每個詞都生成倒排索引,數據量較大。所以倒排索引對應的倒排表被存放在磁碟上。

這樣如果每次查詢都直接讀取磁碟上的倒排表,再查詢目標關鍵詞,會有很多次磁碟IO,嚴重影響查詢性能。為了解磁碟IO問題,Lucene引入排索引的二級索引FST[Finite State Transcer]。原理上可以理解為前綴樹,加速查詢

2)節點的內存查看

3)案例分析

如果節點出現了集群整體響應緩慢,也沒有特別多的數據讀寫。但是發現節點在持續進行Full GC。

常見原因:

Segments個數過多,導致Full GC

我們可以通過查看ElasticSearch的內存分析命令發現:

segments.memory佔用很大空間。

解決方案:

Field data cache 過大,導致Full GC

我們可以查看ElasticSearch的內存使用,發現fielddata.memory.size佔用很大空間。同時,數據不存在寫入和更新,也執行過segments merge。

解決方案:

復雜的嵌套聚合,導致集群Full GC

節點響應緩慢,持續進行Full GC。導出Dump分析。發現內存中有大量 bucket對象,查看日誌,發現復雜的嵌套聚合

解決方案:

4)斷路器

es有多種斷路器,我們可以合理使用,避免不合理操作引發的OOM,每個斷路器可以指定內存使用的限制。

關於es的斷路器使用可以參考官網文檔:

https://www.elastic.co/cn/blog/improving-node-resiliency-with-the-real-memory-circuit-breaker

在排查es問題時,我們會使用一些常見的命令來分析cpu、io、網路等問題。常見的命令如下

我們這里按照1s的頻率輸出磁碟信息

如果想查看和進程關聯的信息,可以使用pidstat或者iotop。

例如,下面為iotop的輸出結果

sar命令可以診斷操作系統內存相關情況。

PS:我們需要關閉內存交換,內存交換會嚴重損害性能

我們知道,操作系統有內核態和用戶態,該命令可以輸出相關信息

Recv-Q和Send-Q代表該連接在內核中等待發送和接收的數據長度。

如果改數據太多,可能原因為應用程序處理不及時或者對端的數據接收不及時,比如網路擁塞之類

本片文章先介紹了es的部署架構,回顧了es節點類型以及它們的配置方式,也了解了不同類型對硬體的要求不一樣。然後總結了幾種不同的架構模式,比如基礎部署、讀寫分離、冷熱分離、異地多活等架構模式,在生產環境中一般我們推薦讀寫分離架構模式,如果可以最好加上冷熱分離,不過配置可能稍微復雜點。

對於容量規劃與調優,首先要明確存儲的數據量和使用場景,推薦內存磁碟比為:搜索類比例(1:16),日誌類(1:48);比如2T的總數據,搜索如果要保持良好的性能的話,每個節點31*16=496G。每個節點實際有400G的存儲空間。那麼2T/400G,則需要5個es存儲節點,每個節點分片數多少合適,文中也有介紹。副本分片數需要根據我們的容錯需求。我們還總結了集群配置和jvm配置相關的優化。

es的使用優化,我們分別總結了寫入和查詢的優化。寫入是其單次數據量、索引refresh、分詞等情況都會影響其吞吐量,我們需要根據實際情況來優化。針對於查詢,我們可以使用api工具進行分析,分析慢耗時發在在哪一步。當es集群出現異常時,如cpu過高、內存fullgc、卡頓、變紅,我們逐一分析了可能的原因和解決辦法,同時也介紹了一些常見的診斷工具和監控api。

我們需要先了解es內部運作的原理,這樣才能根據實際情況正確的設置集群參數和數據模型,還需要結合實際工作遇到的問題不斷的總結經驗,才能用好ElasticSearch。

2. ES的存儲系統

ES 內嵌式存儲系統ES (內嵌式存儲系統(embedded storage,ES))
內嵌式存儲系統(embedded storage,ES),就是把存儲介質內嵌在伺服器中,就好比現在PC中的硬碟。
優點是安裝簡單,維護方便。
缺點是每個伺服器所能夠連接的存儲介質很有限,同時存儲容量和存取速度都受到伺服器性能的限制。內嵌式存儲系統的一個致使缺點是所存儲信息的安全性和可用性必須依賴伺服器,如果伺服器出現故障,其所存儲的信息將不可用。
所以說,內嵌式存儲系統是一個封閉的系統。

3. elasticSearch理論篇—索引、節點、分片

傳統我們檢索文章,是逐個遍歷找到對應關鍵詞的位置;

而倒排索引,是通過分詞策略,形成詞與文章的映射關系表,這種詞典+映射表即為倒排索引。

倒排索引的底層實現是基於:FST(Finite State Transcer)數據結構。
lucene [lu'sen] 從4+版本後開始大量使用的數據結構是FST。FST有兩個優點:

利用es的分片預分配。

不能,因為分片數是 文檔路由演算法 中重要的元素:

shard = hash(routing) % number_of_primary_shards

動態修改分片將意味著幾乎重新索引文檔數據,這是比僅僅將分片從一個節點復制到另一個節點更重量級的操作。

一個分片存在於單個節點,一個節點可以包含多個分片。

elasticSearch天然具有分布式的特徵,實現水平擴容時通過 分片預分配 。在創建索引時,選擇合適的分片數。

隨著數據量的增加,可以動態的增加節點數,elasticSearch將會自動將分片分配到新增的節點上,當重新分配完成時,每個分片將會有接近至少兩倍於之前的運算速度。

elasticSearch中新添加的索引默認被指定了5個主分片。這意味著我們最多可以將那個索引分散到5個節點上,每一個節點一個分片。

不能,一個分片並不是沒有代價的。

es適當的預分配是好的,但是上千個分片就有些糟糕。

ElasticSearch推薦的最大JVM堆空間是30~32G, 所以把你的分片最大容量限制為30GB, 然後再對分片數量做合理估算. 例如, 你認為你的數據能達到200GB, 推薦你最多分配7到8個分片。
在開始階段, 一個好的方案是根據你的節點數量按照1.5~3倍的原則來創建分片. 例如,如果你有3個節點, 則推薦你創建的分片數最多不超過9(3x3)個。當性能下降時,增加節點,ES會平衡分片的放置。
對於基於日期的索引需求, 並且對索引數據的搜索場景非常少. 也許這些索引量將達到成百上千, 但每個索引的數據量只有1GB甚至更小. 對於這種類似場景, 建議只需要為索引分配1個分片。如日誌管理就是一個日期的索引需求,日期索引會很多,但每個索引存放的日誌數據量就很少。

副本分片 可以實現高可用。當持有主分片的節點掛掉之後,一個副本分片將會晉升為主分片的角色。

在索引寫入時,副本分片做著和主分片相同的工作。新文檔首先被索引進主分片然後在同步到其他所有的副本分片。增加副本分片並不會增加索引容量。

副本分片可以服務於讀請求,如果索引偏向查詢,那麼可以通過增加副本的數目來提升查詢性能。但也要為此增加額外的硬體資源。

當使用上面配置時,每一個分片的副本分片數量為1個。

一個擁有兩個主分片一份副本的索引可以在四個節點中橫向擴展

Elasticsearch: 權威指南 » 數據建模 » 擴容設計 » 擴容的單元

面試官:Elasticsearch如何設計索引?滿分答案來了

elasticsearch 設置多少分片合適

新年手打,24道進階必備Elasticsearch 面試真題(建議收藏!)

4. Elasticsearch之存儲原理

倒排索引被寫入磁碟後是不可變的,ES解決不變性和更新索引的方式是使用多個索引,利用新增的索引來反映修改,在查詢時從舊的到新的依次查詢,最後來一個結果合並。

ES底層是基於Lucene,最核心的概念就是 Segment(段) ,每個段本身就是一個倒排索引。

ES中的Index由多個段的集合和 commit point(提交點) 文件組成。

提交點文件中有一個列表存放著所有已知的段,下面是一個帶有1個提交點和3個段的Index示意圖:

Doc會先被搜集到內存中的Buffer內,這個時候還無法被搜索到,如下圖所示:

每隔一段時間,會將buffer提交,在flush磁碟後打開新段使得搜索可見,詳細過程如下:

下面展示了這個過程完成後的段和提交點的狀態:

通過這種方式,可以使得新文檔從被索引到可被搜索間的時間間隔在數分鍾,但是還不夠快。因為磁碟需要 fsync ,這個就成為性能瓶頸。我們前面提到過Doc會先被從buffer刷入段寫入文件系統緩存(很快),那麼就自然想到在這個階段就讓文檔對搜索可見,隨後再被刷入磁碟(較慢)。

Lucene支持對新段寫入和打開,可以使文檔在沒有完全刷入硬碟的狀態下就能對搜索可見,而且是一個開銷較小的操作,可以頻繁進行。

下面是一個已經將Docs刷入段,但還沒有完全提交的示意圖:

我們可以看到,新段雖然還沒有被完全提交,但是已經對搜索可見了。

引入refresh操作的目的是提高ES的實時性,使添加文檔盡可能快的被搜索到,同時又避免頻繁fsync帶來性能開銷,依靠的就是文件系統緩存OS cache里緩存的文件可以被打開(open/reopen)和讀取,而這個os cache實際是一塊內存區域,而非磁碟,所以操作是很快的,這就是ES被稱為近實時搜索的原因。

refresh默認執行的間隔是1秒,可以使用 refreshAPI 進行手動操作,但一般不建議這么做。還可以通過合理設置 refresh_interval 在近實時搜索和索引速度間做權衡。

index segment刷入到os cache後就可以打開供查詢,這個操作是有潛在風險的,因為os cache中的數據有可能在意外的故障中丟失,而此時數據必備並未刷入到os disk,此時數據丟失將是不可逆的,這個時候就需要一種機制,可以將對es的操作記錄下來,來確保當出現故障的時候,已經落地到磁碟的數據不會丟失,並在重啟的時候可以從操作記錄中將數據恢復過來。elasticsearch提供了translog來記錄這些操作,結合os cached segments數據定時落盤來實現數據可靠性保證(flush)。

文檔被添加到buffer同時追加到translog:

進行 refresh 操作,清空buffer,文檔可被搜索但尚未 flush 到磁碟。translog不會清空:

每隔一段時間(例如translog變得太大),index會被flush到磁碟,新的translog文件被創建,commit執行結束後,會發生以下事件:

下面示意圖展示了這個狀態:

translog記錄的是已經 在內存生成(segments)並存儲到os cache但是還沒寫到磁碟的那些索引操作 (注意,有一種解釋說,添加到buffer中但是沒有被存入segment中的數據沒有被記錄到translog中,這依賴於寫translog的時機,不同版本可能有變化,不影響理解),此時這些新寫入的數據可以被搜索到,但是當節點掛掉後這些未來得及落入磁碟的數據就會丟失,可以通過trangslog恢復。

當然translog本身也是磁碟文件,頻繁的寫入磁碟會帶來巨大的IO開銷,因此對translog的追加寫入操作的同樣操作的是os cache,因此也需要定時落盤(fsync)。translog落盤的時間間隔直接決定了ES的可靠性,因為宕機可能導致這個時間間隔內所有的ES操作既沒有生成segment磁碟文件,又沒有記錄到Translog磁碟文件中,導致這期間的所有操作都丟失且無法恢復。

translog的fsync是ES在後台自動執行的,默認是每5秒鍾主動進行一次translog fsync,或者當translog文件大小大於512MB主動進行一次fsync,對應的配置是 index.translog.flush_threshold_period 和 index.translog.flush_threshold_size 。

當 Elasticsearch 啟動的時候, 它會從磁碟中使用最後一個提交點去恢復已知的段,並且會重放 translog 中所有在最後一次提交後發生的變更操作。

translog 也被用來提供實時 CRUD 。當你試著通過ID來RUD一個Doc,它會在從相關的段檢索之前先檢查 translog 中最新的變更。

默認 translog 是每5秒或是每次請求完成後被 fsync 到磁碟(在主分片和副本分片都會)。也就是說,如果你發起一個index, delete, update, bulk請求寫入translog並被fsync到主分片和副本分片的磁碟前不會反回200狀態。

這樣會帶來一些性能損失,可以通過設為非同步fsync,但是必須接受由此帶來的丟失少量數據的風險:

flush 就是執行commit清空、幹掉老translog的過程。默認每個分片30分鍾或者是translog過於大的時候自動flush一次。可以通過flush API手動觸發,但是只會在重啟節點或關閉某個索引的時候這樣做,因為這可以讓未來ES恢復的速度更快(translog文件更小)。

滿足下列條件之一就會觸發沖刷操作:

整體流程:

刪除一個ES文檔不會立即從磁碟上移除,它只是被標記成已刪除。因為段是不可變的,所以文檔既不能從舊的段中移除,舊的段也不能更新以反映文檔最新的版本。

ES的做法是,每一個提交點包括一個 .del 文件(還包括新段),包含了段上已經被標記為刪除狀態的文檔。所以,當一個文檔被做刪除操作,實際上只是在 .del 文件中將該文檔標記為刪除,依然會在查詢時被匹配到,只不過在最終返回結果之前會被從結果中刪除。ES將會在用戶之後添加更多索引的時候,在後台進行要刪除內容的清理。

文檔的更新操作和刪除是類似的:當一個文檔被更新,舊版本的文檔被標記為刪除,新版本的文檔在新的段中索引。
該文檔的不同版本都會匹配一個查詢,但是較舊的版本會從結果中刪除。

通過每秒自動刷新創建新的段,用不了多久段的數量就爆炸了,每個段消費大量文件句柄,內存,cpu資源。更重要的是,每次搜索請求都需要依次檢查每個段。段越多,查詢越慢。

ES通過後台合並段解決這個問題。ES利用段合並的時機來真正從文件系統刪除那些version較老或者是被標記為刪除的文檔。被刪除的文檔(或者是version較老的)不會再被合並到新的更大的段中。

可見,段合並主要有兩個目的:

ES對一個不斷有數據寫入的索引處理流程如下:

合並過程如圖:

從上圖可以看到,段合並之前,舊有的Commit和沒Commit的小段皆可被搜索。

段合並後的操作:

合並完成後新的段可被搜索,舊的段被刪除,如下圖所示:

注意 :段合並過程雖然看起來很爽,但是大段的合並可能會佔用大量的IO和CPU,如果不加以控制,可能會大大降低搜索性能。段合並的optimize API 不是非常特殊的情況下千萬不要使用,默認策略已經足夠好了。不恰當的使用可能會將你機器的資源全部耗盡在段合並上,導致無法搜索、無法響應。

5. ES數據存儲可靠性和寫入流程

https://www.elastic.co/guide/en/elasticsearch/guide/2.x/near-real-time.html
https://www.elastic.co/guide/en/elasticsearch/guide/2.x/merge-process.html

1、數據存儲可靠性保證原理

1.1 translog機制

當一個文檔寫入Lucence後是存儲在內存中的,即使執行了refresh操作仍然是在文件系統緩存中,如果此時伺服器宕機,那麼這部分數據將會丟失

當進行文檔寫操作時會先將文檔寫入Lucene,然後寫入一份到translog,寫入translog是落盤的

tips:如果對可靠性要求不是很高,也可以設置非同步落盤,可以提高性能,由配置index.translog.rability和index.translog.sync_interval控制
tips:translog是追加寫入,因此性能比較好

先寫入Lucene再寫入translog。原因是寫入Lucene可能會失敗,為了減少寫入失敗回滾的復雜度,因此先寫入Lucene

1.2 flush操作

refresh_interval定時觸發 或當translog達到index.translog.flush_threshold_size(默認512mb),ES會觸發一次flush操作:先執行refresh操作將buffer中的數據生成segment,然後調用lucene的commit方法將所有內存中的segment fsync到磁碟,最後會清空translog中的數據(6.x版本為了實現sequenceIDs,不刪除translog) 。

1.3 merge操作
refresh操作會產生大量的小segment,因此產生的每個文件都會消耗文件句柄,內存,CPU 使用等各種資源。更重要的是每個查詢請求都要順序檢查每個segment; segment越多檢索會越慢.
ES會運行一個檢測任務,在後台把近似大小的segment合並成一個新的大segment,並刪除舊segment

1.4、多副本機制
ES有多副本機制(默認是1個副本),一個分片的主副分片不能分片在同一個節點上,進一步保證數據的可靠性。

2、ES寫索引的流程

6. es使用與原理6 -- 聚合分析剖析

有些聚合分析的演算法,是很容易就可以並行的,比如說max

有些聚合分析的演算法,是不好並行的,比如說,count(distinct),並不是說,在每個node上,直接就出一些distinct value,就可以的,因為數據可能會很多,假設圖中的協調節點3百萬個數據去重後還剩下100萬distinct的數據,那麼內存需要來存儲這100萬條數據,這是不可能的

es會採取近似聚合的方式,就是採用在每個node上進行近估計的方式,得到最終的結論,cuont(distcint),100萬,1050萬/95萬 --> 5%左右的錯誤率
近似估計後的結果,不完全准確,但是速度會很快,一般會達到完全精準的演算法的性能的數十倍

precision_threshold優化准確率和內存開銷

brand去重,如果brand的unique value,在100個以內,小米,長虹,三星,TCL,HTL。。。
在多少個unique value以內,cardinality,幾乎保證100%准確
cardinality演算法,會佔用precision_threshold * 8 byte 內存消耗,100 * 8 = 800個位元組
佔用內存很小。。。而且unique value如果的確在值以內,那麼可以確保100%准確
100,數百萬的unique value,錯誤率在5%以內
precision_threshold,值設置的越大,佔用內存越大,1000 * 8 = 8000 / 1000 = 8KB,可以確保更多unique value的場景下,100%的准確
field,去重,count,這時候,unique value,10000,precision_threshold=10000,10000 * 8 = 80000個byte,80KB

doc value正排索引
搜索+聚合 是怎麼實現的?
假設是倒排索引實現的

倒排索引來實現是非常不現實的,因為我們搜索的那個欄位search_field 有可能是分詞的,這就需要去掃描整個索引才能實現聚合操作,效率是及其低下的。
正排索引結構:
doc2: agg1
doc3: agg2
1萬個doc --> 搜 -> 可能跟搜索到10000次,就搜索完了,就找到了1萬個doc的聚合field的所有值了,然後就可以執行分組聚合操作了
doc value原理

1、doc value原理

(1)index-time生成

PUT/POST的時候,就會生成doc value數據,也就是正排索引

(2)核心原理與倒排索引類似

正排索引,也會寫入磁碟文件中,然後呢,os cache先進行緩存,以提升訪問doc value正排索引的性能
如果os cache內存大小不足夠放得下整個正排索引,doc value,就會將doc value的數據寫入磁碟文件中

(3)性能問題:給jvm更少內存,64g伺服器,給jvm最多16g

es官方是建議,es大量是基於os cache來進行緩存和提升性能的,不建議用jvm內存來進行緩存,那樣會導致一定的gc開銷和oom問題
給jvm更少的內存,給os cache更大的內存
64g伺服器,給jvm最多16g,幾十個g的內存給os cache
os cache可以提升doc value和倒排索引的緩存和查詢效率

2、column壓縮

doc1: 550
doc2: 550
doc3: 500

合並相同值,550,doc1和doc2都保留一個550的標識即可
(1)所有值相同,直接保留單值
(2)少於256個值,使用table encoding模式:一種壓縮方式
(3)大於256個值,看有沒有最大公約數,有就除以最大公約數,然後保留這個最大公約數

重點:
對分詞的field,直接執行聚合操作,會報錯,大概意思是說,你必須要打開fielddata,然後將正排索引數據載入到內存中,才可以對分詞的field執行聚合操作,而且會消耗很大的內存
先修改 欄位的fielddata屬性為true,再查 就能查找到數據

當然,我們也可以使用內置field(keyword)不分詞,對string field進行聚合,如果對不分詞的field執行聚合操作,直接就可以執行,不需要設置fieldata=true

分詞field+fielddata的工作原理

doc value --> 不分詞的所有field,可以執行聚合操作 --> 如果你的某個field不分詞,那麼在index-time,就會自動生成doc value --> 針對這些不分詞的field執行聚合操作的時候,自動就會用doc value來執行
分詞field,是沒有doc value的。。。在index-time,如果某個field是分詞的,那麼是不會給它建立doc value正排索引的,因為分詞後,佔用的空間過於大,所以默認是不支持分詞field進行聚合的
分詞field默認沒有doc value,所以直接對分詞field執行聚合操作,是會報錯的

對於分詞field,必須打開和使用fielddata,完全存在於純內存中。。。結構和doc value類似。。。如果是ngram或者是大量term,那麼必將佔用大量的內存。。。

如果一定要對分詞的field執行聚合,那麼必須將fielddata=true,然後es就會在執行聚合操作的時候,現場將field對應的數據,建立一份fielddata正排索引,fielddata正排索引的結構跟doc value是類似的,
但是只會講fielddata正排索引載入到內存中來,然後基於內存中的fielddata正排索引執行分詞field的聚合操作

如果直接對分詞field執行聚合,報錯,才會讓我們開啟fielddata=true,告訴我們,會將fielddata uninverted index,正排索引,載入到內存,會耗費內存空間

為什麼fielddata必須在內存?因為大家自己思考一下,分詞的字元串,需要按照term進行聚合,需要執行更加復雜的演算法和操作,如果基於磁碟和os cache,那麼性能會很差

我們是不是可以預先生成載入fielddata到內存中來???
query-time的fielddata生成和載入到內存,變為index-time,建立倒排索引的時候,會同步生成fielddata並且載入到內存中來,這樣的話,對分詞field的聚合性能當然會大幅度增強

7. 為什麼我的ES文件瀏覽器不能瀏覽外置存儲卡

我的也是,現在還只能用自帶的文件瀏覽器查看..ES瀏覽器只能看內置存儲卡的文件.只不過ES瀏覽器可以查看手機內存裡面的文件.自帶的看不了
我找到了..你用ES瀏覽器點左上角的收藏.再點根目錄有個mnt的文件夾打開.裡面sdcard就是內置存儲卡
sdcard2就是外置存儲卡.把sdcard2設為默認路徑就可以了

8. PB級大規模Elasticsearch集群運維與調優實踐

某中型互聯網公司的游戲業務,使用了騰訊雲的Elasticsearch產品,採用ELK架構存儲業務日誌。因為游戲業務本身的日誌數據量非常大(寫入峰值在100w qps),在服務客戶的幾個月中,踩了不少坑,經過數次優化與調整,把客戶的ES集群調整的比較穩定,避免了在業務高峰時客戶集群的讀寫異常,並且降低了客戶的資金成本和使用成本。下面把服務客戶過程中遇到的典型問題進行梳理,總結經驗,避免再次踩坑。

解決方案架構師A: bellen, XX要上線一款新游戲,日誌存儲決定用ELK架構,他們決定在XX雲和我們之間二選一,我們首先去他們公司和他們交流一下,爭取拿下!

bellen: 好,隨時有空!

。。。

和架構師一起前往該公司,跟負責底層組件的運維部門的負責人進行溝通。

XX公司運維老大:不要講你們的PPT了,先告訴我你們能給我們帶來什麼!

bellen: 。。。呃,我們有很多優勢。。。比如靈活地擴容縮容集群,還可以一鍵平滑升級集群版本,並且提供有跨機房容災的集群從而實現高可用。。

XX公司運維老大:你說的這些別的廠商也有,我就問一個問題,我們現在要存儲一年的游戲日誌,不能刪除數據,每天就按10TB的數據量算,一年也得有個3PB多的數據,這么大的數量,都放在SSD雲盤上,我們的成本太高了,你們有什麼方案既能夠滿足我們存儲這么大數據量的需求,同時能夠降低我們的成本嗎?

bellen: 我們本身提供的有冷熱模式的集群,熱節點採用SSD雲硬碟,冷節點採用SATA盤,採用ES自帶的ILM索引生命周期管理功能定期把較老的索引從熱節點遷移到冷節點上,這樣從整體上可以降低成本。另外一方面,也可以定期把更老的索引通過snapshot快照備份到COS對象存儲中,然後刪除索引,這樣成本就更低了。

XX公司運維老大:存儲到COS就是冷存儲唄,我們需要查詢COS里的數據時,還得再把數據恢復到ES里?這樣不行,速度太慢了,業務等不了那麼長時間,我們的數據不能刪除,只能放在ES里!你們能不能給我們提供一個API, 讓老的索引數據雖然存儲在COS里,但是通過這個API依然可以查詢到數據,而不是先恢復到ES, 再進行查詢?

bellen: 。。。呃,這個可以做,但是需要時間。是否可以採用hadoop on COS的架構,把存量的老的索引數據通過工具導入到COS,通過hive去查詢,這樣成本會非常低,數據依然是隨時可查的。

XX公司運維老大:那不行,我們只想用成熟的ELK架構來做,再增加hadoop那一套東西,我們沒那麼多人力搞這個事!

bellen: 好吧,那可以先搞一個集群測試起來,看看性能怎麼樣。關於存量數據放在COS里但是也需要查詢的問題,我們可以先制定方案,盡快實施起來。

XX公司運維老大:行吧,我們現在按每天10TB數據量預估,先購買一個集群,能撐3個月的數據量就行,能給一個集群配置的建議嗎?

bellen: 目前支持單節點磁碟最大6TB, cpu和內存的話可以放到8核32G單節點,單節點跑2w qps寫入沒有問題,後面也可以進行縱向擴容和橫向擴容。

XX公司運維老大:好,我們先測試一下。

N 天後,架構師A直接在微信群里反饋:"bellen, 客戶反饋這邊的ES集群性能不行啊,使用logstash消費kafka中的日誌數據,跑了快一天了數據還沒追平,這是線上的集群,麻煩緊急看一下吧。。"

我一看,一臉懵, 什麼時候已經上線了啊,不是還在測試中嗎?

XX公司運維小B: 我們購買了8核32G*10節點的集群,單節點磁碟6TB, 索引設置的10分片1副本,現在使用logstash消費kafka中的數據,一直沒有追平,kafka中還有很多數據積壓,感覺是ES的寫入性能有問題。

隨後我立即查看了集群的監控數據,發現cpu和load都很高,jvm堆內存使用率平均都到了90%,節點jvm gc非常頻繁了,部分節點因為響應緩慢,不停的離線又上線。。

經過溝通,發現用戶的使用姿勢是filebeat+kafka+logstash+elasticsearch, 當前已經在kafka中存儲了有10天的日誌數據,啟動了20台logstash進行消費,logstash的batch size也調到了5000,性能瓶頸是在ES這一側。客戶8核32G*10節點的集群,理論上跑10w qps沒有問題,但是logstash消費積壓的數據往ES寫入的qps遠不止10w,所以是ES扛不住寫入壓力了,所以只能對ES集群進行擴容,為了加快存量數據的消費速度,先縱向擴容單節點的配置到32核64GB,之後再橫向增加節點,以保證ES集群能夠最大支持100w qps的寫入(這里需要注意的是,增加節點後索引的分片數量也需要調整)。

所以一般新客戶接入使用ES時,必須要事先評估好節點配置和集群規模,可以從以下幾個方面進行評估:

上述場景2遇到的問題是業務上線前沒有對集群配置和規模進行合理的評估,導致上線後ES集群負載就很高,通過合理的擴容處理,集群最終抗住了寫入壓力。但是又有新的問題出現了。

因為kafka積壓的數據比較多,客戶使用logstash消費kafka數據時,反饋有兩個問題:

經過分析客戶logstash的配置文件,發現問題出現的原因主要是:

分析後,對kafka和logstash進行了如下優化:

通過上述優化,最終使得logstash機器資源都被充分利用上,很快消費完堆積的kafka數據,待消費速度追平生成速度後,logstash消費kafka一直穩定運行,沒有出現積壓。

另外,客戶一開始使用的是5.6.4版本的logstash,版本較老,使用過程中出現因為單個消息體過長導致logstash拋異常後直接退出的問題:

通過把logstash升級至高版本6.8避免了這個問題(6.x版本的logstash修復了這個問題,避免了crash)。

客戶的游戲上線有一個月了,原先預估每天最多有10TB的數據量,實際則是在運營活動期間每天產生20TB的數據,原先6TB*60=360TB總量的數據盤使用率也達到了80%。針對這種情況,我們建議客戶使用冷熱分離的集群架構,在原先60個熱節點的基礎上,增加一批warm節點存儲冷數據,利用ILM(索引生命周期管理)功能定期遷移熱節點上的索引到warm節點上。

通過增加warm節點的方式,客戶的集群磁碟總量達到了780TB, 可以滿足最多三個月的存儲需求。但是客戶的需求還沒有滿足:

XX公司運維老大:給我們一個能存放一年數據的方案吧,總是通過加節點擴容磁碟的方式不是長久之計,我們得天天盯著這個集群,運維成本很高!並且一直加節點,ES會扛不住吧?

bellen: 可以嘗試使用我們新上線的支持本地盤的機型,熱節點最大支持7.2TB的本地SSD盤,warm節點最大支持48TB的本地SATA盤。一方面熱節點的性能相比雲盤提高了,另外warm節點可以支持更大的磁碟容量。單節點可以支持的磁碟容量增大了,節點數量就不用太多了,可以避免踩到因為節點數量太多而觸發的坑。

XX公司運維老大:現在用的是雲盤,能替換成本地盤嗎,怎麼替換?

bellen: 不能直接替換,需要在集群中新加入帶本地盤的節點,把數據從老的雲盤節點遷移到新的節點上,遷移完成後再剔除掉舊的節點,這樣可以保證服務不會中斷,讀寫都可以正常進行。

XX公司運維老大:好,可以實施,盡快搞起來!

雲盤切換為本地盤,是通過調用雲服務後台的API自動實施的。在實施之後,觸發了數據從舊節點遷移到新節點的流程,但是大約半個小時候,問題又出現了:

XX公司運維小B: bellen, 快看一下,ES的寫入快掉0了。

bellen: 。。。

通過查看集群監控,發現寫入qps直接由50w降到1w,寫入拒絕率猛增,通過查看集群日誌,發現是因為當前小時的索引沒有創建成功導致寫入失敗。

緊急情況下,執行了以下操作定位到了原因:

經過了這次擴容操作,總結了如下經驗:

在穩定運行了一陣後,集群又出問題了。。

XX公司運維小B: bellen, 昨晚凌晨1點鍾之後,集群就沒有寫入了,現在kafka里有大量的數據堆積,麻煩盡快看一下?

bellen: 。。。

通過cerebro查看集群,發現集群處於yellow狀態,然後發現集群有大量的錯誤日誌:

然後再進一步查看集群日誌,發現有"master not discovered yet..."之類的錯誤日誌,檢查三個master節點,發現有兩個master掛掉,只剩一個了,集群無法選主。

登陸到掛了了master節點機器上,發現保活程序無法啟動es進程,第一直覺是es進程oom了;此時也發現master節點磁碟使用率100%, 檢查了JVM堆內存快照文件目錄,發現有大量的快照文件,於是刪除了一部分文件,重啟es進程,進程正常啟動了;但是問題是堆內存使用率太高,gc非常頻繁,master節點響應非常慢,大量的創建索引的任務都超時,阻塞在任務隊列中,集群還是無法恢復正常。

看到集群master節點的配置是16核32GB內存,JVM實際只分配了16GB內存,此時只好通過對master節點原地增加內存到64GB(虛擬機,使用的騰訊雲CVM, 可以調整機器規格,需要重啟),master節點機器重啟之後,修改了es目錄jvm.options文件,調整了堆內存大小,重新啟動了es進程。

3個master節點都恢復正常了,但是分片還需要進行恢復,通過GET _cluster/health看到集群當前有超過10w個分片,而這些分片恢復還需要一段時間,通過調大"cluster.routing.allocation.node_concurrent_recoveries", 增大分片恢復的並發數量。實際上5w個主分片恢復的是比較快的了,但是副本分片的恢復就相對慢很多,因為部分副本分片需要從主分片上同步數據才能恢復。此時可以採取的方式是把部分舊的索引副本數量調為0, 讓大量副本分片恢復的任務盡快結束,保證新索引能夠正常創建,從而使得集群能夠正常寫入。

總結這次故障的根本原因是集群的索引和分片數量太多,集群元數據佔用了大量的堆內存,而master節點本身的JVM內存只有16GB(數據節點有32GB), master節點頻繁full gc導致master節點異常,從而最終導致整個集群異常。所以要解決這個問題,還是得從根本上解決集群的分片數量過多的問題。

目前日誌索引是按照小時創建,60分片1副本,每天有24*60*2=2880個分片,每個月就產生86400個分片,這么多的分片可能會帶來嚴重的問題。有以下幾種方式解決分片數量過多的問題:

和客戶溝通過後,客戶表示可以接受方式1和方式2,但是方式3和4不能接受,因為考慮到存在磁碟故障的可能性,必須保留一個副本來保證數據的可靠性;另外還必須保證所有數據都是隨時可查詢的,不能關閉。

在場景5中,雖然通過臨時給master節點增加內存,抗住了10w分片,但是不能從根本上解決問題。客戶的數據是計劃保留一年的,如果不進行優化,集群必然扛不住數十萬個分片。所以接下來需要著重解決集群整體分片數量過多的問題,在場景5的最後提到了,用戶可以接受開啟shrink以及降低索引創建粒度(經過調整後,每兩個小時創建一個索引),這在一定程度上減少了分片的數量,能夠使集群暫時穩定一陣。

輔助客戶在kibana上配置了如下的ILM策略:

在warm phase, 把創建時間超過360小時的索引從hot節點遷移到warm節點上,保持索引的副本數量為1,之所以使用360小時作為條件,而不是15天作為條件,是因為客戶的索引是按小時創建的,如果以15天作為遷移條件,則在每天凌晨都會同時觸發15天前的24個索引一共24*120=2880個分片同時開始遷移索引,容易引發場景4中介紹的由於遷移分片數量過多導致創建索引被阻塞的問題,所以以360小時作為條件,則在每個小時只會執行一個索引的遷移,這樣把24個索引的遷移任務打平,避免其它任務被阻塞的情況發生。

同時,也在warm phase階段,設置索引shrink,把索引的分片數縮成5個,因為老的索引已經不執行寫入了,所以也可以執行force merge, 強制把segment文件合並為1個,可以獲得更好的查詢性能。

另外,設置了ILM策略後,可以在索引模板里增加index.lifecycle.name配置,使得所有新創建的索引都可以和新添加的ILM策略關聯,從而使得ILM能夠正常運行。

客戶使用的ES版本是6.8.2, 在運行ILM的過程中, 也發現一些問題:

這是因為shrink操作需要新把索引完整的一份數據都遷移到一個節點上,然後在內存中構建新的分片元數據,把新的分片通過軟鏈接指向到幾個老的分片的數據,在ILM中執行shrink時,ILM會對索引進行如下配置:

問題是索引包含副本,而主分片和副本分片又不能在同一個節點上,所以會出現部分分片無法分配的情況(不是全部,只有一部分),這里應該是觸發了6.8版本的ILM的bug,需要查看源碼才能定位解決這個bug,目前還在研究中。當前的workaround是通過腳本定期掃描出現unassigned shards的索引,修改其settings:

優先保證分片先從hot節點遷移到warm節點,這樣後續的shrink才能順利執行(也可能執行失敗,因為60個分片都在一個節點上,可能會觸發rebalance, 導致分片遷移走,shrink的前置條件又不滿足,導致執行失敗)。要完全規避這個問題,還得在ILM策略中設置,滿足創建時間超過360個小時的索引,副本直接調整為0,但是客戶又不接受,沒辦法。

在場景5和6中,介紹了10w個分片會給集群帶來的影響和通過開啟shrink來降低分片數量,但是仍然有兩個需要重點解決的問題:

可以估算一下,按小時建索引,60分片1副本,一年的分片數為24*120*365=1051200個分片,執行shrink後分片數量24*10*350 + 24*120*15 = 127200(15天內的新索引為了保障寫入性能和數據可靠性,仍然保持60分片1副本,舊的索引shrink為5分片1副本), 仍然有超過10w個分片。結合集群一年總的存儲量和單個分片可以支持的數據量大小進行評估,我們期望集群總體的分片數量可以穩定為6w~8w,怎麼優化?

可以想到的方案是執行數據冷備份,把比較老的索引都冷備到其它的存儲介質上比如HDFS,S3,騰訊雲的COS對象存儲等,但是問題是這些冷備的數據如果也要查詢,需要先恢復到ES中才可查,恢復速度比較慢,客戶無法接受。由此也產生了新的想法,目前老的索引仍然是1副本,可以把老索引先進行冷備份,再把副本調為0,這樣做有以下幾點好處:

經過和客戶溝通,客戶接受了上述方案,計劃把老索引冷備到騰訊雲的對象存儲COS中,實施步驟為:

其中步驟1的實施可以通過腳本實現,本案例中採用騰訊雲SCF雲函數進行實施,方便快捷可監控。實施要點有:

在實施完步驟1之後,就可以批量把對索引進行過備份的索引副本數都調為0, 這樣一次性釋放了很多磁碟空間,並且顯著降低了集群整體的分片數量。

接下來實施步驟2,需要每天執行一次快照,多創建時間較久的索引進行備份,實施比較簡單,可以通過crontab定時執行腳本或者使用騰訊雲SCF執行。

步驟2實施之後,就可以修改ILM策略,開啟cold phase, 修改索引副本數量為0:

此處的timing是創建時間20天後,需要保證步驟2中對過去老索引數據備份先執行完成才可以進入到cold phase.

通過老索引數據冷備並且降低索引副本,我們可以把集群整體的分片數量維持在一個較低的水位,但是還有另外一個問題待解決,也即shrink失敗的問題。剛好,我們可以利用對老索引數據冷備並且降低索引副本的方案,來徹底解決shrink失敗的問題。

在場景5中有提到,shrink失敗歸根接地是因為索引的副本數量為1, 現在我們可以吧數據備份和降低副本提前,讓老索引進入到ILM的warm phase中時已經是0副本,之後再執行shrink操作就不會有問題了;同時,因為副本降低了,索引從hot節點遷移到warm節點遷移的數據量也減少了一半,從而降低了集群負載,一舉兩得。

因此,我們需要修改ILM策略,在warm phase就把索引的副本數量調整為0, 然後去除cold phase。

另外一個可選的優化項是,對老的索引進行凍結,凍結索引是指把索引常駐內存的一些數據從內存中清理掉(比如FST, 元數據等), 從而降低內存使用量,而在查詢已經凍結的索引時,會重新構建出臨時的索引數據結構存放在內存中,查詢完畢再清理掉;需要注意的是,默認情況下是無法查詢已經凍結的索引的,需要在查詢時顯式的增加"ignore_throttled=false"參數。

經過上述優化,我們最終解決了集群整體分片數量過多和shrink失敗的問題。在實施過程中引入了額外的定時任務腳本實施自動化快照,實際上在7.4版本的ES中,已經有這個功能了,特性名稱為 SLM (快照生命周期管理),並且可以結合ILM使用,在ILM中增加了"wait_for_snapshot"的ACTION, 但是卻只能在delete phase中使用,不滿足我們的場景。

在上述的場景4-7中,我們花費大量的精力去解決問題和優化使用方式,保證ES集群能夠穩定運行,支持PB級別的存儲。溯本回原,如果我們能有一個方案使得客戶只需要把熱數據放在SSD盤上,然後冷數據存儲到COS/S3上,但同時又使冷數據能夠支持按需隨時可查,那我們前面碰到的所有問題都迎刃而解了。可以想像得到的好處有:

而這正是目前es開源社區正在開發中的Searchable Snapshots功能,從 Searchable Snapshots API 的官方文檔上可以看到,我們可以創建一個索引,將其掛載到一個指定的快照中,這個新的索引是可查詢的,雖然查詢時間可能會慢點,但是在日誌場景中,對一些較老的索引進行查詢時,延遲大點一般都是可以接受的。

所以我認為,Searchable Snapshots解決了很多痛點,將會給ES帶了新的繁榮!

經歷過上述運維和優化ES集群的實踐,我們總結到的經驗有:

從一開始和客戶進行接觸,了解客戶訴求,逐步解決ES集群的問題,最終使得ES集群能夠保持穩定,這中間的經歷讓我真真正正的領悟到"實踐出真知",只有不斷實踐,才能對異常情況迅速做出反應,以及對客戶提的優化需求迅速反饋。

9. ES集群原理與搭建

查看集群健康狀況:URL+ /GET _cat/health

Cluster

代表一個集群,集群中有多個節點,其中有一個為主節點,這個主節點是可以通過選舉產生的,主從節點是對於集群內部來說的。es的一個概念就是去中心化,字面上理解就是無中心節點,這是對於集群外部來說的,因為從外部來看es集群,在邏輯上是個整體,你與任何一個節點的通信和與整個es集群通信是等價的。

Shards

代表索引分片,es可以把一個完整的索引分成多個分片,這樣的好處是可以把一個大的索引拆分成多個,分布到不同的節點上。構成分布式搜索。分片的數量只能在索引創建前指定,並且索引創建後不能更改。

replicas

代表索引副本,es可以設置多個索引的副本,副本的作用一是提高系統的容錯性,當某個節點某個分片損壞或丟失時可以從副本中恢復。二是提高es的查詢效率,es會自動對搜索請求進行負載均衡。

Recovery

代表數據恢復或叫數據重新分布,es在有節點加入或退出時會根據機器的負載對索引分片進行重新分配,掛掉的節點重新啟動時也會進行數據恢復。

(2)、ES為什麼要實現集群

在單台ES伺服器節點上,隨著業務量的發展索引文件慢慢增多,會影響到效率和內存存儲問題等。

我們可以採用ES集群,將單個索引的分片到多個不同分布式物理機器上存儲,從而可以實現高可用、容錯性等。

ES集群中索引可能由多個分片構成,並且每個分片可以擁有多個副本。通過將一個單獨的索引分為多個分片,我們可以處理不能在一個單一的伺服器上面運行的大型索引,簡單的說就是索引的大小過大,導致效率問題。不能運行的原因可能是內存也可能是存儲。由於每個分片可以有多個副本,通過將副本分配到多個伺服器,可以提高查詢的負載能力。

(3)、ES是如何解決高並發

ES是一個分布式全文檢索框架,隱藏了復雜的處理機制,內部使用 分片機制、集群發現、分片負載均衡請求路由。

Shards 分片:代表索引分片,es可以把一個完整的索引分成多個分片,這樣的好處是可以把一個大的索引拆分成多個,分布到不同的節點上。構成分布式搜索。分片的數量只能在索引創建前指定,並且索引創建後不能更改。

Replicas分片:代表索引副本,es可以設置多個索引的副本,副本的作用一是提高系統的容錯性,當某個節點某個分片損壞或丟失時可以從副本中恢復。二是提高es的查詢效率,es會自動對搜索請求進行負載均衡。

1、每個索引會被分成多個分片shards進行存儲,默認創建索引是分配5個分片進行存儲。每個分片都會分布式部署在多個不同的節點上進行部署,該分片成為primary shards。

注意:索引的主分片primary shards定義好後,後面不能做修改。

2、為了實現高可用數據的高可用,主分片可以有對應的備分片replics shards,replic shards分片承載了負責容錯、以及請求的負載均衡。

注意: 每一個主分片為了實現高可用,都會有自己對應的備分片,主分片對應的備分片不能存放同一台伺服器上。主分片primary shards可以和其他replics shards存放在同一個node節點上。

3、documnet routing(數據路由)

當客戶端發起創建document的時候,es需要確定這個document放在該index哪個shard上。這個過程就是數據路由。

路由演算法:shard = hash(routing) % number_of_primary_shards

如果number_of_primary_shards在查詢的時候取余發生的變化,無法獲取到該數據

注意:索引的主分片數量定義好後,不能被修改

高可用視圖分析(下圖所示:上面的圖,如果節點1與節點2宕機了,es集群數據就不完整了。下面圖,如果節點1與節點2宕機了,es集群數據還是完整的)

(1)、伺服器環境

准備三台伺服器集群

| 伺服器名稱 | IP地址 |
| node-1 | 192.168.212.182 |
| node-2 | 192.168.212.183 |
| node-3 | 192.168.212.184 |

(2)、關閉防火牆

(3)、**** http://192.168.212.185:9200/_cat/nodes?pretty

*號表示為master節點

注意:

注意克隆data文件會導致數據不同步

報該錯誤解決辦法 :

failed to send join request to master

因為克隆導致data文件也克隆呢,直接清除每台伺服器data文件。