<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Elasticsearch 架構原理

          共 17114字,需瀏覽 35分鐘

           ·

          2021-08-18 20:54


          來源:《ELKstack權威指南》

          • 架構原理
          • 帶著問題學習
          • segment、buffer和translog對實時性的影響
            • 動態(tài)更新的 Lucene 索引
            • translog 提供的磁盤同步控制
            • Elasticsearch 分布式索引
          • segment merge對寫入性能的影響
            • 歸并線程配置
            • 歸并策略
            • forcemerge 接口
          • routing和replica的讀寫過程
            • 路由計算
            • 副本一致性
          • shard 的 allocate 控制
            • reroute 接口
            • 分配失敗原因
            • 節(jié)點下線
            • 冷熱數(shù)據(jù)的讀寫分離
          • 集群自動發(fā)現(xiàn)

          架構原理

          本書作為 Elastic Stack 指南,關注于 Elasticsearch 在日志和數(shù)據(jù)分析場景的應用,并不打算對底層的 Lucene 原理或者 Java 編程做詳細的介紹,但是 Elasticsearch 層面上的一些架構設計,對我們做性能調(diào)優(yōu),故障處理,具有非常重要的影響。

          所以,作為 ES 部分的起始章節(jié),先從數(shù)據(jù)流向和分布的層面,介紹一下 ES 的工作原理,以及相關的可控項。各位讀者可以跳過這節(jié)先行閱讀后面的運維操作部分,但作為性能調(diào)優(yōu)的基礎知識,依然建議大家抽時間返回來了解。

          推薦下自己做的 Spring Boot 的實戰(zhàn)項目:

          https://github.com/YunaiV/ruoyi-vue-pro

          帶著問題學習

          1. 寫入的數(shù)據(jù)是如何變成elasticsearch里可以被檢索和聚合的索引內(nèi)容的?

          2. lucene如何實現(xiàn)準實時索引?

          3. 什么是segment?

          4. 什么是commit?

          5. segment的數(shù)據(jù)來自哪里?

          6. segment在寫入磁盤前就可以被檢索,是因為利用了什么?

          7. elasticsearch中的refresh操作是什么?配置項是哪個?設置的命令是什么?

          8. refresh只是寫到了文件系統(tǒng)緩存,那么實際寫入磁盤是由什么控制呢?,如果這期間發(fā)生錯誤和故障,數(shù)據(jù)會不會丟失?

          9. 什么是translog日志?什么時候會被清空?什么是flush操作?配置項是什么?怎么配置?

          10. 什么是段合并?為什么要段合并?段合并線程配置項?段合并策略?怎么forcemerge(optimize)?

          11. routing的規(guī)則是什么樣的?replica讀寫過程?wait_for_active_shards參數(shù)timeout參數(shù) ?

          12. reroute 接口?

          13. 兩種 自動發(fā)現(xiàn)方式?

          推薦下自己做的 Spring Cloud 的實戰(zhàn)項目:

          https://github.com/YunaiV/onemall

          segment、buffer和translog對實時性的影響

          既然介紹數(shù)據(jù)流向,首先第一步就是:寫入的數(shù)據(jù)是如何變成 Elasticsearch 里可以被檢索和聚合的索引內(nèi)容的?

          以單文件的靜態(tài)層面看,每個全文索引都是一個詞元的倒排索引,具體涉及到全文索引的通用知識,這里不單獨介紹,有興趣的讀者可以閱讀《Lucene in Action》等書籍詳細了解。

          動態(tài)更新的 Lucene 索引

          以在線動態(tài)服務的層面看,要做到實時更新條件下數(shù)據(jù)的可用和可靠,就需要在倒排索引的基礎上,再做一系列更高級的處理。

          其實總結一下 Lucene 的處理辦法,很簡單,就是一句話:新收到的數(shù)據(jù)寫到新的索引文件里

          Lucene 把每次生成的倒排索引,叫做一個段(segment)。然后另外使用一個 commit 文件,記錄索引內(nèi)所有的 segment。而生成 segment 的數(shù)據(jù)來源,則是內(nèi)存中的 buffer。也就是說,動態(tài)更新過程如下:

          1. 當前索引有 3 個 segment 可用。索引狀態(tài)如圖 2-1; 
          2. 新接收的數(shù)據(jù)進入內(nèi)存 buffer。索引狀態(tài)如圖 2-2; 
          3. 內(nèi)存 buffer 刷到磁盤,生成一個新的 segment,commit 文件同步更新。索引狀態(tài)如圖 2-3。 

          利用磁盤緩存實現(xiàn)的準實時檢索

          既然涉及到磁盤,那么一個不可避免的問題就來了:磁盤太慢了!對我們要求實時性很高的服務來說,這種處理還不夠。所以,在第 3 步的處理中,還有一個中間狀態(tài):

          1. 內(nèi)存 buffer 生成一個新的 segment,刷到文件系統(tǒng)緩存中,Lucene 即可檢索這個新 segment。索引狀態(tài)如圖 2-4。

          2. 文件系統(tǒng)緩存真正同步到磁盤上,commit 文件更新。達到圖 2-3 中的狀態(tài)。

          這一步刷到文件系統(tǒng)緩存的步驟,在 Elasticsearch 中,是默認設置為 1 秒間隔的,對于大多數(shù)應用來說,幾乎就相當于是實時可搜索了。Elasticsearch 也提供了單獨的 /_refresh 接口,用戶如果對 1 秒間隔還不滿意的,可以主動調(diào)用該接口來保證搜索可見。

          注:5.0 中還提供了一個新的請求參數(shù):?refresh=wait_for,可以在寫入數(shù)據(jù)后不強制刷新但一直等到刷新才返回。

          不過對于 Elastic Stack 的日志場景來說,恰恰相反,我們并不需要如此高的實時性,而是需要更快的寫入性能。所以,一般來說,我們反而會通過 /_settings 接口或者定制 template 的方式,加大 refresh_interval 參數(shù):

          # curl -XPOST http://127.0.0.1:9200/logstash-2015.06.21/_settings -d'
          "refresh_interval""10s" }
          '

          如果是導入歷史數(shù)據(jù)的場合,那甚至可以先完全關閉掉:

          # curl -XPUT http://127.0.0.1:9200/logstash-2015.05.01 -d'
          {
            "settings" : {
              "refresh_interval""-1"
            }
          }'

          在導入完成以后,修改回來或者手動調(diào)用一次即可:

          # curl -XPOST http://127.0.0.1:9200/logstash-2015.05.01/_refresh

          translog 提供的磁盤同步控制

          既然 refresh 只是寫到文件系統(tǒng)緩存,那么第 4 步寫到實際磁盤又是有什么來控制的?如果這期間發(fā)生主機錯誤、硬件故障等異常情況,數(shù)據(jù)會不會丟失?

          這里,其實有另一個機制來控制。Elasticsearch 在把數(shù)據(jù)寫入到內(nèi)存 buffer 的同時,其實還另外記錄了一個 translog 日志。也就是說,第 2 步并不是圖 2-2 的狀態(tài),而是像圖 2-5 這樣:


          在第 3 和第 4 步,refresh 發(fā)生的時候,translog 日志文件依然保持原樣,如圖 2-6:


          也就是說,如果在這期間發(fā)生異常,Elasticsearch 會從 commit 位置開始,恢復整個 translog 文件中的記錄,保證數(shù)據(jù)一致性。

          等到真正把 segment 刷到磁盤,且 commit 文件進行更新的時候, translog 文件才清空。這一步,叫做 flush。同樣,Elasticsearch 也提供了 /_flush 接口。

          對于 flush 操作,Elasticsearch 默認設置為:每 30 分鐘主動進行一次 flush,或者當 translog 文件大小大于 512MB (老版本是 200MB)時,主動進行一次 flush。這兩個行為,可以分別通過 index.translog.flush_threshold_periodindex.translog.flush_threshold_size 參數(shù)修改。

          如果對這兩種控制方式都不滿意,Elasticsearch 還可以通過 index.translog.flush_threshold_ops 參數(shù),控制每收到多少條數(shù)據(jù)后 flush 一次。

          translog 的一致性

          索引數(shù)據(jù)的一致性通過 translog 保證。那么 translog 文件自己呢?

          默認情況下,Elasticsearch 每 5 秒,或每次請求操作結束前,會強制刷新 translog 日志到磁盤上。

          后者是 Elasticsearch 2.0 新加入的特性。為了保證不丟數(shù)據(jù),每次 index、bulk、delete、update 完成的時候,一定觸發(fā)刷新 translog 到磁盤上,才給請求返回 200 OK。這個改變在提高數(shù)據(jù)安全性的同時當然也降低了一點性能。

          如果你不在意這點可能性,還是希望性能優(yōu)先,可以在 index template 里設置如下參數(shù):

          {    "index.translog.durability""async"}

          Elasticsearch 分布式索引

          大家可能注意到了,前面一段內(nèi)容,一直寫的是"Lucene 索引"。這個區(qū)別在于,Elasticsearch 為了完成分布式系統(tǒng),對一些名詞概念作了變動。索引成為了整個集群級別的命名,而在單個主機上的Lucene 索引,則被命名為分片(shard)。至于數(shù)據(jù)是怎么識別到自己應該在哪個分片,請閱讀稍后有關 routing 的章節(jié)。

          segment merge對寫入性能的影響

          通過上節(jié)內(nèi)容,我們知道了數(shù)據(jù)怎么進入 ES 并且如何才能讓數(shù)據(jù)更快的被檢索使用。其中用一句話概括了 Lucene 的設計思路就是"開新文件"。從另一個方面看,開新文件也會給服務器帶來負載壓力。因為默認每 1 秒,都會有一個新文件產(chǎn)生,每個文件都需要有文件句柄,內(nèi)存,CPU 使用等各種資源。一天有 86400 秒,設想一下,每次請求要掃描一遍 86400 個文件,這個響應性能絕對好不了!

          為了解決這個問題,ES 會不斷在后臺運行任務,主動將這些零散的 segment 做數(shù)據(jù)歸并,盡量讓索引內(nèi)只保有少量的,每個都比較大的,segment 文件。這個過程是有獨立的線程來進行的,并不影響新 segment 的產(chǎn)生。歸并過程中,索引狀態(tài)如圖 2-7,尚未完成的較大的 segment 是被排除在檢索可見范圍之外的:


          當歸并完成,較大的這個 segment 刷到磁盤后,commit 文件做出相應變更,刪除之前幾個小 segment,改成新的大 segment。等檢索請求都從小 segment 轉到大 segment 上以后,刪除沒用的小 segment。這時候,索引里 segment 數(shù)量就下降了,狀態(tài)如圖 2-8 所示:


          歸并線程配置

          segment 歸并的過程,需要先讀取 segment,歸并計算,再寫一遍 segment,最后還要保證刷到磁盤。可以說,這是一個非常消耗磁盤 IO 和 CPU 的任務。所以,ES 提供了對歸并線程的限速機制,確保這個任務不會過分影響到其他任務。

          在 5.0 之前,歸并線程的限速配置 indices.store.throttle.max_bytes_per_sec 是 20MB。對于寫入量較大,磁盤轉速較高,甚至使用 SSD 盤的服務器來說,這個限速是明顯過低的。對于 Elastic Stack 應用,社區(qū)廣泛的建議是可以適當調(diào)大到 100MB或者更高。

          # curl -XPUT http://127.0.0.1:9200/_cluster/settings -d'
          {
              "persistent" : {
                  "indices.store.throttle.max_bytes_per_sec" : "100mb"
              }
          }'

          5.0 開始,ES 對此作了大幅度改進,使用了 Lucene 的 CMS(ConcurrentMergeScheduler) 的 auto throttle 機制,正常情況下已經(jīng)不再需要手動配置 indices.store.throttle.max_bytes_per_sec 了。官方文檔中都已經(jīng)刪除了相關介紹,不過從源碼中還是可以看到,這個值目前的默認設置是 10240 MB。

          歸并線程的數(shù)目,ES 也是有所控制的。默認數(shù)目的計算公式是:Math.min(3, Runtime.getRuntime().availableProcessors() / 2)。即服務器 CPU 核數(shù)的一半大于 3 時,啟動 3 個歸并線程;否則啟動跟 CPU 核數(shù)的一半相等的線程數(shù)。相信一般做 Elastic Stack 的服務器 CPU 合數(shù)都會在 6 個以上。所以一般來說就是 3 個歸并線程。如果你確定自己磁盤性能跟不上,可以降低 index.merge.scheduler.max_thread_count 配置,免得 IO 情況更加惡化。

          歸并策略

          歸并線程是按照一定的運行策略來挑選 segment 進行歸并的。主要有以下幾條:

          • index.merge.policy.floor_segment 默認 2MB,小于這個大小的 segment,優(yōu)先被歸并。
          • index.merge.policy.max_merge_at_once 默認一次最多歸并 10 個 segment
          • index.merge.policy.max_merge_at_once_explicit 默認 forcemerge 時一次最多歸并 30 個 segment。
          • index.merge.policy.max_merged_segment 默認 5 GB,大于這個大小的 segment,不用參與歸并。forcemerge 除外。

          根據(jù)這段策略,其實我們也可以從另一個角度考慮如何減少 segment 歸并的消耗以及提高響應的辦法:加大 flush 間隔,盡量讓每次新生成的 segment 本身大小就比較大。

          forcemerge 接口

          既然默認的最大 segment 大小是 5GB。那么一個比較龐大的數(shù)據(jù)索引,就必然會有為數(shù)不少的 segment 永遠存在,這對文件句柄,內(nèi)存等資源都是極大的浪費。但是由于歸并任務太消耗資源,所以一般不太選擇加大 index.merge.policy.max_merged_segment 配置,而是在負載較低的時間段,通過 forcemerge 接口,強制歸并 segment。

          # curl -XPOST http://127.0.0.1:9200/logstash-2015-06.10/_forcemerge?max_num_segments=1

          由于 forcemerge 線程對資源的消耗比普通的歸并線程大得多,所以,絕對不建議對還在寫入數(shù)據(jù)的熱索引執(zhí)行這個操作。這個問題對于 Elastic Stack 來說非常好辦,一般索引都是按天分割的。更合適的任務定義方式,請閱讀本書稍后的 curator 章節(jié)。

          routing和replica的讀寫過程

          之前兩節(jié),完整介紹了在單個 Lucene 索引,即 ES 分片內(nèi)的數(shù)據(jù)寫入流程。現(xiàn)在徹底回到 ES 的分布式層面上來,當一個 ES 節(jié)點收到一條數(shù)據(jù)的寫入請求時,它是如何確認這個數(shù)據(jù)應該存儲在哪個節(jié)點的哪個分片上的?

          路由計算

          作為一個沒有額外依賴的簡單的分布式方案,ES 在這個問題上同樣選擇了一個非常簡潔的處理方式,對任一條數(shù)據(jù)計算其對應分片的方式如下:

          shard = hash(routing) % number_of_primary_shards

          每個數(shù)據(jù)都有一個 routing 參數(shù),默認情況下,就使用其 _id 值。將其 _id 值計算哈希后,對索引的主分片數(shù)取余,就是數(shù)據(jù)實際應該存儲到的分片 ID。

          由于取余這個計算,完全依賴于分母,所以導致 ES 索引有一個限制,索引的主分片數(shù),不可以隨意修改。因為一旦主分片數(shù)不一樣,所以數(shù)據(jù)的存儲位置計算結果都會發(fā)生改變,索引數(shù)據(jù)就完全不可讀了。

          副本一致性

          作為分布式系統(tǒng),數(shù)據(jù)副本可算是一個標配。ES 數(shù)據(jù)寫入流程,自然也涉及到副本。在有副本配置的情況下,數(shù)據(jù)從發(fā)向 ES 節(jié)點,到接到 ES 節(jié)點響應返回,流向如下(附圖 2-9):

          1. 客戶端請求發(fā)送給 Node 1 節(jié)點,注意圖中 Node 1 是 Master 節(jié)點,實際完全可以不是。

          2. Node 1 用數(shù)據(jù)的 _id 取余計算得到應該講數(shù)據(jù)存儲到 shard 0 上。通過 cluster state 信息發(fā)現(xiàn) shard 0 的主分片已經(jīng)分配到了 Node 3 上。Node 1 轉發(fā)請求數(shù)據(jù)給 Node 3。

          3. Node 3 完成請求數(shù)據(jù)的索引過程,存入主分片 0。然后并行轉發(fā)數(shù)據(jù)給分配有 shard 0 的副本分片的 Node 1 和 Node 2。當收到任一節(jié)點匯報副本分片數(shù)據(jù)寫入成功,Node 3 即返回給初始的接收節(jié)點 Node 1,宣布數(shù)據(jù)寫入成功。Node 1 返回成功響應給客戶端。


          圖片

          這個過程中,有幾個參數(shù)可以用來控制或變更其行為:

          • wait_for_active_shards 上面示例中,2 個副本分片只要有 1 個成功,就可以返回給客戶端了。這點也是有配置項的。其默認值的計算來源如下:

          int( (primary + number_of_replicas) / 2 ) + 1

          根據(jù)需要,也可以將參數(shù)設置為 one,表示僅寫完主分片就返回,等同于 async;還可以設置為 all,表示等所有副本分片都寫完才能返回。

          • timeout 如果集群出現(xiàn)異常,有些分片當前不可用,ES 默認會等待 1 分鐘看分片能否恢復。可以使用 ?timeout=30s 參數(shù)來縮短這個等待時間。

          副本配置和分片配置不一樣,是可以隨時調(diào)整的。有些較大的索引,甚至可以在做 forcemerge 前,先把副本全部取消掉,等 optimize 完后,再重新開啟副本,節(jié)約單個 segment 的重復歸并消耗。

          # curl -XPUT http://127.0.0.1:9200/logstash-mweibo-2015.05.02/_settings -d '{
          "index": { "number_of_replicas" : 0 }
          }'

          shard 的 allocate 控制

          某個 shard 分配在哪個節(jié)點上,一般來說,是由 ES 自動決定的。以下幾種情況會觸發(fā)分配動作:

          1. 新索引生成

          2. 索引的刪除

          3. 新增副本分片

          4. 節(jié)點增減引發(fā)的數(shù)據(jù)均衡

          ES 提供了一系列參數(shù)詳細控制這部分邏輯:

          • cluster.routing.allocation.enable 該參數(shù)用來控制允許分配哪種分片。默認是 all。可選項還包括 primariesnew_primariesnone 則徹底拒絕分片。該參數(shù)的作用,本書稍后集群升級章節(jié)會有說明。

          • cluster.routing.allocation.allow_rebalance 該參數(shù)用來控制什么時候允許數(shù)據(jù)均衡。默認是 indices_all_active,即要求所有分片都正常啟動成功以后,才可以進行數(shù)據(jù)均衡操作,否則的話,在集群重啟階段,會浪費太多流量了。

          • cluster.routing.allocation.cluster_concurrent_rebalance 該參數(shù)用來控制集群內(nèi) 同時運行的數(shù)據(jù)均衡任務個數(shù)。默認是 2 個。如果有節(jié)點增減,且集群負載壓力不高的時候,可以適當加大。

          • cluster.routing.allocation.node_initial_primaries_recoveries 該參數(shù)用來控制節(jié)點 重啟時,允許同時恢復幾個主分片。默認是 4 個。如果節(jié)點是多磁盤,且 IO 壓力不大,可以適當加大。

          • cluster.routing.allocation.node_concurrent_recoveries 該參數(shù)用來控制節(jié)點 除了主分片重啟恢復以外其他情況下,允許同時運行的數(shù)據(jù)恢復任務。默認是 2 個。所以,節(jié)點重啟時,可以看到主分片迅速恢復完成,副本分片的恢復卻很慢。除了副本分片本身數(shù)據(jù)要通過網(wǎng)絡復制以外,并發(fā)線程本身也減少了一半。當然,這種設置也是有道理的——主分片一定是本地恢復,副本分片卻需要走網(wǎng)絡,帶寬是有限的。從 ES 1.6 開始,冷索引的副本分片可以本地恢復,這個參數(shù)也就是可以適當加大了。

          • indices.recovery.concurrent_streams 該參數(shù)用來控制節(jié)點 從網(wǎng)絡復制恢復副本分片時的數(shù)據(jù)流個數(shù)。默認是 3 個。可以配合上一條配置一起加大。

          • indices.recovery.max_bytes_per_sec 該參數(shù)用來控制節(jié)點 恢復時的速率。默認是 40MB。顯然是比較小的,建議加大。

          此外,ES 還有一些其他的分片分配控制策略。比如以 tagrack_id 作為區(qū)分等。一般來說,Elastic Stack 場景中使用不多。運維人員可能比較常見的策略有兩種:

          1. 磁盤限額 為了保護節(jié)點數(shù)據(jù)安全,ES 會定時(cluster.info.update.interval,默認 30 秒)檢查一下各節(jié)點的數(shù)據(jù)目錄磁盤使用情況。在達到 cluster.routing.allocation.disk.watermark.low (默認 85%)的時候,新索引分片就不會再分配到這個節(jié)點上了。在達到 cluster.routing.allocation.disk.watermark.high (默認 90%)的時候,就會觸發(fā)該節(jié)點現(xiàn)存分片的數(shù)據(jù)均衡,把數(shù)據(jù)挪到其他節(jié)點上去。這兩個值不但可以寫百分比,還可以寫具體的字節(jié)數(shù)。有些公司可能出于成本考慮,對磁盤使用率有一定的要求,需要適當抬高這個配置:
          # curl -XPUT localhost:9200/_cluster/settings -d '{
          "transient" : {
          "cluster.routing.allocation.disk.watermark.low" : "85%",
          "cluster.routing.allocation.disk.watermark.high" : "10gb",
          "cluster.info.update.interval" : "1m"
          }
          }'
          1. 熱索引分片不均 默認情況下,ES 集群的數(shù)據(jù)均衡策略是以各節(jié)點的分片總數(shù)(indices_all_active)作為基準的。這對于搜索服務來說無疑是均衡搜索壓力提高性能的好辦法。但是對于 Elastic Stack 場景,一般壓力集中在新索引的數(shù)據(jù)寫入方面。正常運行的時候,也沒有問題。但是當集群擴容時,新加入集群的節(jié)點,分片總數(shù)遠遠低于其他節(jié)點。這時候如果有新索引創(chuàng)建,ES 的默認策略會導致新索引的所有主分片幾乎全分配在這臺新節(jié)點上。整個集群的寫入壓力,壓在一個節(jié)點上,結果很可能是這個節(jié)點直接被壓死,集群出現(xiàn)異常。所以,對于 Elastic Stack 場景,強烈建議大家預先計算好索引的分片數(shù)后,配置好單節(jié)點分片的限額。比如,一個 5 節(jié)點的集群,索引主分片 10 個,副本 1 份。則平均下來每個節(jié)點應該有 4 個分片,那么就配置:
          # curl -s -XPUT http://127.0.0.1:9200/logstash-2015.05.08/_settings -d '{
          "index": { "routing.allocation.total_shards_per_node" : "5" }
          }'

          注意,這里配置的是 5 而不是 4。因為我們需要預防有機器故障,分片發(fā)生遷移的情況。如果寫的是 4,那么分片遷移會失敗。

          此外,另一種方式則更加玄妙,Elasticsearch 中有一系列參數(shù),相互影響,最終聯(lián)合決定分片分配:

          • cluster.routing.allocation.balance.shard 節(jié)點上分配分片的權重,默認為 0.45。數(shù)值越大越傾向于在節(jié)點層面均衡分片。
          • cluster.routing.allocation.balance.index 每個索引往單個節(jié)點上分配分片的權重,默認為 0.55。數(shù)值越大越傾向于在索引層面均衡分片。
          • cluster.routing.allocation.balance.threshold 大于閾值則觸發(fā)均衡操作。默認為1。

          Elasticsearch 中的計算方法是:

          (indexBalance (node.numShards(index) – avgShardsPerNode(index)) + shardBalance (node.numShards() – avgShardsPerNode)) <=> weightthreshold

          所以,也可以采取加大 cluster.routing.allocation.balance.index,甚至設置 cluster.routing.allocation.balance.shard 為 0 來盡量采用索引內(nèi)的節(jié)點均衡。

          reroute 接口

          上面說的各種配置,都是從策略層面,控制分片分配的選擇。在必要的時候,還可以通過 ES 的 reroute 接口,手動完成對分片的分配選擇的控制。

          reroute 接口支持五種指令:allocate_replica, allocate_stale_primary, allocate_empty_primarymovecancel。常用的一般是 allocate 和 move:

          • allocate_* 指令

          因為負載過高等原因,有時候個別分片可能長期處于 UNASSIGNED 狀態(tài),我們就可以手動分配分片到指定節(jié)點上。默認情況下只允許手動分配副本分片(即使用 allocate_replica),所以如果要分配主分片,需要單獨加一個 accept_data_loss 選項:

          # curl -XPOST 127.0.0.1:9200/_cluster/reroute -d '{
          "commands" : [ {
          "allocate_stale_primary" :
          {
          "index" : "logstash-2015.05.27""shard" : 61"node" : "10.19.0.77""accept_data_loss" : true
          }
          }
          ]
          }'

          注意,allocate_stale_primary 表示準備分配到的節(jié)點上可能有老版本的歷史數(shù)據(jù),運行時請?zhí)崆按_認一下是哪個節(jié)點上保留有這個分片的實際目錄,且目錄大小最大。然后手動分配到這個節(jié)點上。以此減少數(shù)據(jù)丟失。

          • move 指令

          因為負載過高,磁盤利用率過高,服務器下線,更換磁盤等原因,可以會需要從節(jié)點上移走部分分片:

          curl -XPOST 127.0.0.1:9200/_cluster/reroute -d '{
          "commands" : [ {
          "move" :
          {
          "index" : "logstash-2015.05.22""shard" : 0"from_node" : "10.19.0.81""to_node" : "10.19.0.104"
          }
          }
          ]
          }'

          分配失敗原因

          如果是自己手工 reroute 失敗,Elasticsearch 返回的響應中會帶上失敗的原因。不過格式非常難看,一堆 YES,NO。從 5.0 版本開始,Elasticsearch 新增了一個 allocation explain 接口,專門用來解釋指定分片的具體失敗理由:

          curl -XGET 'http://localhost:9200/_cluster/allocation/explain' -d'{
          "index""logstash-2016.10.31",
          "shard"0,
          "primary"false

          }'

          得到的響應如下:

          {
            "shard" : {
              "index" : "myindex",
              "index_uuid" : "KnW0-zELRs6PK84l0r38ZA",
              "id" : 0,
              "primary" : false
            },
            "assigned" : false,
            "shard_state_fetch_pending"false,
            "unassigned_info" : {
              "reason" : "INDEX_CREATED",
              "at" : "2016-03-22T20:04:23.620Z"
            },
            "allocation_delay_ms" : 0,
            "remaining_delay_ms" : 0,
            "nodes" : {
              "V-Spi0AyRZ6ZvKbaI3691w" : {
                "node_name" : "H5dfFeA",
                "node_attributes" : {
                  "bar" : "baz"
                },
                "store" : {
                  "shard_copy" : "NONE"
                },
                "final_decision" : "NO",
                "final_explanation" : "the shard cannot be assigned because one or more allocation decider returns a 'NO' decision",
                "weight" : 0.06666675,
                "decisions" : [ {
                  "decider" : "filter",
                  "decision" : "NO",
                  "explanation" : "node does not match index include filters [foo:\"bar\"]"
                }  ]
              },
              "Qc6VL8c5RWaw1qXZ0Rg57g" : {
                ...

          這會是很長一串 JSON,把集群里所有的節(jié)點都列上來,挨個解釋為什么不能分配到這個節(jié)點。

          節(jié)點下線

          集群中個別節(jié)點出現(xiàn)故障預警等情況,需要下線,也是 Elasticsearch 運維工作中常見的情況。如果已經(jīng)穩(wěn)定運行過一段時間的集群,每個節(jié)點上都會保存有數(shù)量不少的分片。這種時候通過 reroute 接口手動轉移,就顯得太過麻煩了。這個時候,有另一種方式:

          curl -XPUT 127.0.0.1:9200/_cluster/settings -d '{
          "transient" :{
          "cluster.routing.allocation.exclude._ip" : "10.0.0.1"
          }
          }'

          Elasticsearch 集群就會自動把這個 IP 上的所有分片,都自動轉移到其他節(jié)點上。等到轉移完成,這個空節(jié)點就可以毫無影響的下線了。

          _ip 類似的參數(shù)還有 _host, _name 等。此外,這類參數(shù)不單是 cluster 級別,也可以是 index 級別。下一小節(jié)就是 index 級別的用例。

          冷熱數(shù)據(jù)的讀寫分離

          Elasticsearch 集群一個比較突出的問題是: 用戶做一次大的查詢的時候, 非常大量的讀 IO 以及聚合計算導致機器 Load 升高, CPU 使用率上升, 會影響阻塞到新數(shù)據(jù)的寫入, 這個過程甚至會持續(xù)幾分鐘。所以,可能需要仿照 MySQL 集群一樣,做讀寫分離。

          實施方案

          1. N 臺機器做熱數(shù)據(jù)的存儲, 上面只放當天的數(shù)據(jù)。這 N 臺熱數(shù)據(jù)節(jié)點上面的 elasticsearc.yml 中配置 node.tag: hot

          2. 之前的數(shù)據(jù)放在另外的 M 臺機器上。這 M 臺冷數(shù)據(jù)節(jié)點中配置 node.tag: stale

          3. 模板中控制對新建索引添加 hot 標簽:

             {
             "order" : 0,
             "template" : "*",
             "settings" : {
               "index.routing.allocation.require.tag" : "hot"
               }
             }
          4. 每天計劃任務更新索引的配置, 將 tag 更改為 stale, 索引會自動遷移到 M 臺冷數(shù)據(jù)節(jié)點


          # curl -XPUT http://127.0.0.1:9200/indexname/_settings -d'
          {
          "index": {
             "routing": {
                "allocation": {
                   "require": {
                      "tag""stale"
                   }
                }
            }
          }
          }'
          1. 這樣,寫操作集中在 N 臺熱數(shù)據(jù)節(jié)點上,大范圍的讀操作集中在 M 臺冷數(shù)據(jù)節(jié)點上。避免了堵塞影響。

          該方案運用的,是 Elasticsearch 中的 allocation filter 功能,詳細說明見:https://www.elastic.co/guide/en/elasticsearch/reference/master/shard-allocation-filtering.html

          集群自動發(fā)現(xiàn)

          ES 是一個 P2P 類型(使用 gossip 協(xié)議)的分布式系統(tǒng),除了集群狀態(tài)管理以外,其他所有的請求都可以發(fā)送到集群內(nèi)任意一臺節(jié)點上,這個節(jié)點可以自己找到需要轉發(fā)給哪些節(jié)點,并且直接跟這些節(jié)點通信。

          所以,從網(wǎng)絡架構及服務配置上來說,構建集群所需要的配置極其簡單。在 Elasticsearch 2.0 之前,無阻礙的網(wǎng)絡下,所有配置了相同 cluster.name 的節(jié)點都自動歸屬到一個集群中。

          2.0 版本之后,基于安全的考慮,Elasticsearch 稍作了調(diào)整,避免開發(fā)環(huán)境過于隨便造成的麻煩。

          unicast 方式

          ES 從 2.0 版本開始,默認的自動發(fā)現(xiàn)方式改為了單播(unicast)方式。配置里提供幾臺節(jié)點的地址,ES 將其視作 gossip router 角色,借以完成集群的發(fā)現(xiàn)。由于這只是 ES 內(nèi)一個很小的功能,所以 gossip router 角色并不需要單獨配置,每個 ES 節(jié)點都可以擔任。所以,采用單播方式的集群,各節(jié)點都配置相同的幾個節(jié)點列表作為 router 即可。

          此外,考慮到節(jié)點有時候因為高負載,慢 GC 等原因可能會有偶爾沒及時響應 ping 包的可能,一般建議稍微加大 Fault Detection 的超時時間。

          同樣基于安全考慮做的變更還有監(jiān)聽的主機名。現(xiàn)在默認只監(jiān)聽本地 lo 網(wǎng)卡上。所以正式環(huán)境上需要修改配置為監(jiān)聽具體的網(wǎng)卡。

          network.host: "192.168.0.2"
          discovery.zen.minimum_master_nodes: 3
          discovery.zen.ping_timeout: 100s
          discovery.zen.fd.ping_timeout: 100s
          discovery.zen.ping.unicast.hosts: ["10.19.0.97","10.19.0.98","10.19.0.99","10.19.0.100"]

          上面的配置中,兩個 timeout 可能會讓人有所迷惑。這里的 fd 是 fault detection 的縮寫。也就是說:

          • discovery.zen.ping_timeout 參數(shù)僅在加入或者選舉 master 主節(jié)點的時候才起作用;
          • discovery.zen.fd.ping_timeout 參數(shù)則在穩(wěn)定運行的集群中,master 檢測所有節(jié)點,以及節(jié)點檢測 master 是否暢通時長期有用。

          既然是長期有用,自然還有運行間隔和重試的配置,也可以根據(jù)實際情況調(diào)整:

          discovery.zen.fd.ping_interval: 10s
          discovery.zen.fd.ping_retries: 10


          推薦閱讀:

          世界的真實格局分析,地球人類社會底層運行原理

          不是你需要中臺,而是一名合格的架構師(附各大廠中臺建設PPT)

          企業(yè)IT技術架構規(guī)劃方案

          論數(shù)字化轉型——轉什么,如何轉?

          華為干部與人才發(fā)展手冊(附PPT)

          企業(yè)10大管理流程圖,數(shù)字化轉型從業(yè)者必備!

          【中臺實踐】華為大數(shù)據(jù)中臺架構分享.pdf

          華為的數(shù)字化轉型方法論

          華為如何實施數(shù)字化轉型(附PPT)

          超詳細280頁Docker實戰(zhàn)文檔!開放下載

          華為大數(shù)據(jù)解決方案(PPT)

          瀏覽 46
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产成人婬片A片免费V8 | 夜色视频在线播放 | 大香蕉大香蕉免费网 | 中文字幕第一区综合 | 播五月婷婷|