㈠ lucene創建了索引,是不是已經等於緩存了所有數據了
看來樓主是剛接觸lucene。
lucene在磁碟上建立的索引,就是數據內容的本身,索引一旦建立,就和資料庫沒有任何關系了。按樓主的說法就是:已經包含了全部的內容。
lucene的數據是不是緩存到本地,這個問題要看自己的設置。在建立索引的時候,有兩種方式,一個是在內存中建立索引,一個是在本地磁碟建立索引。第一種方式,當電腦重啟之後就會消失。第二種方式是在本地磁碟建立了文件,可以被長期保留。
㈡ 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 不是非常特殊的情況下千萬不要使用,默認策略已經足夠好了。不恰當的使用可能會將你機器的資源全部耗盡在段合並上,導致無法搜索、無法響應。
㈢ ElasticSearch數據存儲內容
很多使用Elasticsearch的同學會關心數據存儲在ES中的存儲容量,會有這樣的疑問:xxTB的數據入到ES會使用多少存儲空間。這個問題其實很難直接回答的,只有數據寫入ES後,才能觀察到實際的存儲空間。比如同樣是1TB的數據,寫入ES的存儲空間可能差距會非常大,可能小到只有300~400GB,也可能多到6-7TB,為什麼會造成這么大的差距呢?究其原因,我們來探究下Elasticsearch中的數據是如何存儲。文章中我以Elasticsearch 2.3版本為示例,對應的lucene版本是5.5,Elasticsearch現在已經來到了6.5版本,數字類型、列存等存儲結構有些變化,但基本的概念變化不多,文章中的內容依然適用。
Elasticsearch對外提供的是index的概衡塌慶念,可以類比為DB,用咐握戶查詢是在index上完成的,衫皮每個index由若干個shard組成,以此來達到分布式可擴展的能力。比如下圖是一個由10個shard組成的index。
shard是Elasticsearch數據存儲的最小單位,index的存儲容量為所有shard的存儲容量之和。Elasticsearch集群的存儲容量則為所有index存儲容量之和。
一個shard就對應了一個lucene的library。對於一個shard,Elasticsearch增加了translog的功能,類似於HBase WAL,是數據寫入過程中的中間數據,其餘的數據都在lucene庫中管理的。
所以Elasticsearch索引使用的存儲內容主要取決於lucene中的數據存儲。
下面我們主要看下lucene的文件內容,在了解lucene文件內容前,大家先了解些lucene的基本概念。
lucene包的文件是由很多segment文件組成的,segments_xxx文件記錄了lucene包下面的segment文件數量。每個segment會包含如下的文件。
下面我們以真實的數據作為示例,看看lucene中各類型數據的容量佔比。
寫100w數據,有一個uuid欄位,寫入的是長度為36位的uuid,字元串總為3600w位元組,約為35M。
數據使用一個shard,不帶副本,使用默認的壓縮演算法,寫入完成後merge成一個segment方便觀察。
使用線上默認的配置,uuid存為不分詞的字元串類型。創建如下索引:
首先寫入100w不同的uuid,使用磁碟容量細節如下:
可以看到正排數據、倒排索引數據,列存數據容量佔比幾乎相同,正排數據和倒排數據還會存儲Elasticsearch的唯一id欄位,所以容量會比列存多一些。
35M的uuid存入Elasticsearch後,數據膨脹了3倍,達到了122.7mb。Elasticsearch竟然這么消耗資源,不要著急下結論,接下來看另一個測試結果。
我們寫入100w一樣的uuid,然後看看Elasticsearch使用的容量。
這回35M的數據Elasticsearch容量只有13.2mb,其中還有主要的佔比還是Elasticsearch的唯一id,100w的uuid幾乎不佔存儲容積。
所以在Elasticsearch中建立索引的欄位如果基數越大(count distinct),越佔用磁碟空間。
我們再看看存100w個不一樣的整型會是如何。
從結果可以看到,100w整型數據,Elasticsearch的存儲開銷為13.6mb。如果以int型計算100w數據的長度的話,為400w位元組,大概是3.8mb數據。忽略Elasticsearch唯一id欄位的影響,Elasticsearch實際存儲容量跟整型數據長度差不多。
我們再看一下開啟最佳壓縮參數對存儲空間的影響:
結果中可以發現,只有正排數據會啟動壓縮,壓縮能力確實強勁,不考慮唯一id欄位,存儲容量大概壓縮到接近50%。
我們還做了一些實驗,Elasticsearch默認是開啟_all參數的,_all可以讓用戶傳入的整體json數據作為全文檢索的欄位,可以更方便的檢索,但在現實場景中已經使用的不多,相反會增加很多存儲容量的開銷,可以看下開啟_all的磁碟空間使用情況:
開啟_all比不開啟多了40mb的存儲空間,多的數據都在倒排索引上,大約會增加30%多的存儲開銷。所以線上都直接禁用。
然後我還做了其他幾個嘗試,為了驗證存儲容量是否和數據量成正比,寫入1000w數據的uuid,發現存儲容量基本為100w數據的10倍。我還驗證了數據長度是否和數據量成正比,發現把uuid增長2倍、4倍,存儲容量也響應的增加了2倍和4倍。在此就不一一列出數據了。
文件名為:segments_xxx
該文件為lucene數據文件的元信息文件,記錄所有segment的元數據信息。
該文件主要記錄了目前有多少segment,每個segment有一些基本信息,更新這些信息定位到每個segment的元信息文件。
lucene元信息文件還支持記錄userData,Elasticsearch可以在此記錄translog的一些相關信息。
文件後綴:.si
每個segment都有一個.si文件,記錄了該segment的元信息。
segment元信息文件中記錄了segment的文檔數量,segment對應的文件列表等信息。
文件後綴:.fnm
該文件存儲了fields的基本信息。
fields信息中包括field的數量,field的類型,以及IndexOpetions,包括是否存儲、是否索引,是否分詞,是否需要列存等等。
文件後綴:.fdx, .fdt
索引文件為.fdx,數據文件為.fdt,數據存儲文件功能為根據自動的文檔id,得到文檔的內容,搜索引擎的術語習慣稱之為正排數據,即doc_id -> content,es的_source數據就存在這
索引文件記錄了快速定位文檔數據的索引信息,數據文件記錄了所有文檔id的具體內容。
索引後綴:.tip,.tim
倒排索引也包含索引文件和數據文件,.tip為索引文件,.tim為數據文件,索引文件包含了每個欄位的索引元信息,數據文件有具體的索引內容。
5.5.0版本的倒排索引實現為FST tree,FST tree的最大優勢就是內存空間佔用非常低 ,具體可以參看下這篇文章: http://www.cnblogs.com/bonelee/p/6226185.html
http://examples.mikemccandless.com/fst.py?terms=&cmd=Build+it 為FST圖實例,可以根據輸入的數據構造出FST圖
生成的 FST 圖為:
文件後綴:.doc, .pos, .pay
.doc保存了每個term的doc id列表和term在doc中的詞頻
全文索引的欄位,會有.pos文件,保存了term在doc中的位置
全文索引的欄位,使用了一些像payloads的高級特性才會有.pay文件,保存了term在doc中的一些高級特性
文件後綴:.dvm, .dvd
索引文件為.dvm,數據文件為.dvd。
lucene實現的docvalues有如下類型:
其中SORTED_SET 的 SORTED_SINGLE_VALUED類型包括了兩類數據 : binary + numeric, binary是按ord排序的term的列表,numeric是doc到ord的映射。
㈣ 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。
㈤ Lucene 的存儲結構概述
lucene的檢索演算法屬於索引檢索,即用空間來換取時間,對需要檢索的文件、字元流進行全文索引,在檢索的時候對索引進行快速的檢索,得到檢索位置,這個位置記錄檢索詞出現的文件路徑或者某個關鍵詞。
lucene 在存儲它的全文索引結構時,是有層次結構的,這涉及到5個層次:索引(Index);段(Segment);文檔(Document);域(Field);詞(Term),他們的關系如下圖所示:(lucene 索引存儲結構概念圖)
下圖是Lucene生成的索引的一個實例,右邊是對虧橘首這5個層次的描述:
Lucene的索引結構是有層次結構的,主要分以下幾個層次:
Lucene的索引結構中銷數,即保存了正向信息,也保存了反向信息。
所謂正向信息:
所謂反向信息:
段(Segment) 的控制策略
在建立索引的時候對性能影響最伍如大的地方就是在將索引寫入文件的時候, 所以在具體應用的時候就需要對此加以控制:
Lucene默認情況是每加入10份文檔(Document)就從內存往index文件寫入並生成一個段(Segment) ,然後每10個段(Segment)就合並成一個段(Segment). 這些控制的變數如下:
MaxMergeDocs用於控制一個segment文件中最多包含的Document數.比如限制為100的話,即使當前有10個segment也不會合並,因為合並後的segment將包含1000個文檔,超過了限制。
MinMergeDocs用於確定一個當內存中文檔達到多少的時候才寫入文件,該項對segment的數量和大小不會有什麼影響,它僅僅影響內存的使用,進一步影響寫索引的效率。
㈥ 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寫索引的流程