PB級數據實時查詢,滴滴Elasticsearch多集羣架構實踐

點擊上方"IT牧場",選擇"設爲星標"技術乾貨每日送達node

點擊上方"IT牧場", 右上角選擇「設爲星標」面試

精品技術文章準時送上!微信


「Elasticsearch 是基於 Lucene 實現的分佈式搜索引擎,提供了海量數據實時檢索和分析能力。

 

 

Elastic 公司開源的一系列產品組成的 Elastic Stack,能夠爲日誌服務、搜索引擎、系統監控等提供簡單、易用的解決方案。網絡



滴滴 Elasticsearch 簡介架構



滴滴 2016 年初開始構建 Elasticsearch 平臺,現在已經發展到超過 3500+Elasticsearch 實例,超過 5PB 的數據存儲,峯值寫入 TPS 超過了 2000w/s 的超大規模。併發

Elasticsearch 在滴滴有着很是豐富的使用場景,例如線上核心的打車地圖搜索,客服、運營的多維度查詢,滴滴日誌服務等近千個平臺用戶。app

超大的規模和豐富的場景給滴滴 Elasticsearch 平臺帶來了極大的挑戰,咱們在這期間積累了豐富經驗,也取得了一些成果。本文給你們分享滴滴在 Elasticsearch 多集羣架構的實踐。dom

單集羣架構瓶頸elasticsearch

介紹單集羣架構瓶頸前,先來看下滴滴 Elasticsearch 單集羣的架構。分佈式

滴滴 Elasticsearch 單集羣架構

 

 

滴滴在單集羣架構的時候,寫入和查詢就已經經過 Sink 服務和 Gateway 服務管控起來。

①Sink 服務

滴滴幾乎全部寫入 Elasticsearch 的數據都是經由 Kafka 消費入到 Elasticsearch。

Kafka 的數據包括業務 log 數據、MySQL Binlog 數據和業務自主上報的數據,Sink 服務將這些數據實時消費入到 Elasticsearch。

最初設計 Sink 服務是想對寫入 Elasticsearch 集羣進行管控,保護 Elasticsearch 集羣,防止海量的數據寫入拖垮 Elasticsearch。

以後咱們也一直沿用了 Sink 服務,並將該服務從 Elasticsearch 平臺分離出去,成立滴滴 Sink 數據投遞平臺,能夠從 Kafka 或者 MQ 實時同步數據到 Elasticsearch、HDFS、Ceph 等多個存儲服務。

有了多集羣架構後,Elasticsearch 平臺能夠消費一份 MQ 數據寫入多個 Elasticsearch 集羣,作到集羣級別的容災,還能經過 MQ 回溯數據進行故障恢復。

②Gateway 服務

全部業務的查詢都是通過 Gateway 服務,Gateway 服務實現了 Elasticsearch 的 HTTP Restful 和TCP協議。

業務方能夠經過 Elasticsearch 各語言版本的 SDK 直接訪問 Gateway 服務,Gateway 服務還實現了 SQL 接口,業務方能夠直接使用 SQL 訪問 Elasticsearch 平臺。

Gateway 服務最初提供了應用權限的管控,訪問記錄,限流、降級等基本能力,後面隨着平臺演進,Gateway 服務還提供了索引存儲分離、DSL 級別的限流、多集羣災備等能力。

③Admin 服務

整個 Elasticsearch 平臺由 Admin 服務統一管控起來。Admin 服務提供了索引的生命週期管理,索引容量自動規劃,索引健康分,集羣監控等豐富的平臺能力,以及爲 Sink、Gateway 服務提供索引、權限等元數據信息。

Elasticsearch 單集羣瓶頸

隨着滴滴 Elasticsearch 平臺規模的快速發展,Elasticsearch 集羣愈來愈大,最大的時候,是由幾百臺物理機組成集羣,當時集羣共 3000+ 的索引,超過了 50000 個 Shard,集羣總容量達到了 PB 級別。

超大的 Elasticsearch 集羣面臨了很大的穩定性風險,這些風險主要來自於如下三個方面:

  • Elasticsearch 架構瓶頸

  • 索引資源共享風險

  • 業務場景差別大

 

Elasticsearch 架構瓶頸

Elasticsearch 架構在集羣變大到必定的規模會遇到瓶頸,瓶頸主要跟 Elasticsearch 任務處理模型有關。

Elasticsearch 看起來是 P2P 架構,但實際上,仍然是中心化的分佈式架構。

整個集羣只有一個 Active Master。Master 負責整個集羣的元數據管理。

集羣的全部元數據保存在 ClusterState 對象中,主要包括全局的配置信息、索引信息和節點信息。只要元數據發生修改,都得由 Master 完成。

ElasticsearchMaster 的任務處理是單線程完成的,每次處理任務,涉及到 ClusterState 的改動,都會將最新的 ClusterState 對象 Publish 給集羣的所有節點,並阻塞等待所有節點接受到變動消息,處理完變動任務後,才完成本次任務。

這樣的架構模型致使在集羣規模變大的時候出現很嚴重的穩定性風險:

  • 若是有節點假死,好比 JVM 內存被打滿,進程還存活着,響應 Master 任務時間會很長,影響單個任務的完成時間。

  • 有大量恢復任務的時候,因爲 Master 是單線程處理的,全部任務須要排隊處理,產生大量的 pending_tasks。恢復時間變得很長。

  • Elasticsearch 的任務分了優先級,例如 put-mapping 任務優先級低於建立、恢復索引,若是一些業務上低優先級索引在恢復,正常索引有新字段寫入時會被阻塞。

  • Master 任務處理模型,在任務執行完成後,會回調大量 Listener 處理元數據變動。

    其中有些回調邏輯在索引、Shard 膨脹後,會出現處理緩慢的問題,當 Shard 膨脹到 5-6w 時,一些任務處理須要 8-9s 的時間,嚴重影響了集羣的恢復能力。

針對這些問題,Elasticsearch 也在不斷優化,針對相同類型的任務,好比 put-mapping 任務,Master 會一次性處理全部堆積在隊列裏的相同任務。

ClusterState 對象只傳遞 diff 內容,優化回調 Listener 模塊的處理耗時環節等等。

可是因爲整個集羣的任務都集中在一個 Master 的一個線程中處理,在線程中須要同步元數據變動給集羣的每一個節點,並阻塞等待所有節點同步完成。這個模型在集羣規模不斷膨脹時,穩定性會不斷降低。

①索引資源共享風險

Elasticsearch 索引是由多個 Shard 組成,Master 會動態給這些 Shard 分配節點資源。不一樣的索引會存在資源混部的狀況。

 

 

Elasticsearch 經過 Shard Allocation Awareness 的設計,能夠將集羣的節點按集合劃分紅不一樣的 Rack。

在分配索引時能夠指定 Rack 列表,這樣索引就只會分配在指定 Rack 對應的節點列表中,從而作到物理資源的隔離。

可是實際使用中,不少容量小的索引因爲佔用資源有限,會混部在一些節點中。

這種狀況下,會由於個別索引的查詢、寫入量飆升,而影響到其餘索引的穩定性。若是出現了節點故障,就會影響到整個集羣的穩定性。

整個集羣 Master、Clientnode 資源是共享的,Master 風險前面已經單獨說起,Clientnode 共享帶來的 GC、抖動、異常問題都會影響到集羣內的所有索引。

②業務場景差別大

Elasticsearch 適用的業務場景差別特別大:

  • 針對線上核心的入口搜索,通常按城市劃分索引後,索引容量不大,數據沒有實時寫入或者實時寫入 TPS 很小。

    好比地圖 POI 數據採用離線更新的方式,外賣商家、菜品寫入量也很小。可是查詢的 QPS 很高,查詢對 RT 的平均時間和抖動狀況要求很高。

  • 針對日誌檢索的場景,實時寫入量特別大,有些索引甚至超過了 100w/s 的 TPS,該場景對吞吐量要求很高,但對查詢 QPS 和查詢 RT 要求不高。

  • 針對 Binlog 數據的檢索,寫入量相比日誌會小不少,可是對查詢的複雜度、QPS 和 RT 有必定的要求。

  • 針對監控、分析類的場景,聚合查詢需求會比較多,對 Elasticsearch 內存壓力較大,容易引發節點的抖動和 GC。

這些場景各異,穩定性、性能要求各不相同的場景,一個 Elasticsearch 集羣即便使用各類優化手段,很難所有知足需求,最好的方式仍是按業務場景劃分 Elasticsearch 集羣。

多集羣挑戰

正是單集羣面臨了很是大的穩定性風險,咱們開始規劃多集羣的架構。咱們在設計多集羣方案的時候,指望對業務方是零感知的。

寫入仍是通過 Kafka,Sink 服務能夠將不一樣 Topic 的數據入到不一樣的 Elasticsearch 集羣。

查詢繼續經過 Gateway 服務,並且業務方仍然像以前同樣傳遞索引名稱,而無需感知到平臺內部的索引分佈。全部的索引在不一樣集羣的分佈細節,均由 Gateway 服務屏蔽。

整個改造最大的挑戰在於查詢方式的兼容。Elasticsearch 查詢索引的方式很是靈活,能夠支持 * 號做爲通配符匹配。

這樣一個索引 Query 可能查詢的是多個索引,好比有以下 3 個索引:

  • index_a

  • index_b

  • index_c

使用 index* 查詢的時候,能夠同時查詢到 index_a、index_b、index_c 三個索引。

Elasticsearch 這種實現方式很是簡單,因爲一次 Query 最終查詢的是多個 Shard 的數據。

因此不管對於具體的索引,仍是模糊的索引,都是先根據索引名稱獲得 Shard 列表,再將多個 Shard 的 Query 結果 Merge 到一塊兒返回。

這樣的使用方式,對於多集羣方案就會遇到問題,好比 index_a 在 A 集羣,index_b 在 B 集羣、index_c 在 C 集羣,對於 index* 的 Query,就沒法在一個集羣上完成。

Tribenode 介紹

通過調研,咱們發現 Elasticsearch Tribenode 特性能夠很好的知足多集羣查詢的特性。

Tribenode 的實現很是巧妙。org.elasticsearch.tribe 包下只有三個文件,核心類是 TribeService。

Tribenode 的核心原理就是 Merge 每一個集羣的 ClusterState 對象成一個公共的 ClusterState 對象,ClusterState 包含了索引、Shard 和節點數據分佈表。

而 Elasticsearch 的工做邏輯都是基於 ClusterState 元數據驅動的,因此對外看起來就是一個包含所有索引的 Clientnode。

 

 

Tribenode 經過配置多個 Elasticsearch 集羣地址,而後以 Clientnode 角色分別鏈接每一個集羣,每一個集羣看起來會多了一個 Clientnode。

Tribenode 經過該 Clientnode 角色獲取到集羣的 ClusterState 信息,並綁定 Listener 監聽 ClusterState 變化。

Tribenode 將獲取的全部集羣的 ClusterState 信息 Merge 到一塊兒,造成一個對外部訪問使用的 ClusterState 對象,對外提供服務。

Tribenode 除了註冊 Listener 和 Merge ClusterState,其餘的全部邏輯都是複用了 Clientnode 的代碼。

能夠看到 Tribenode 的優勢:

  • 可以知足多集羣訪問的需求,對外使用是透明的。

  • 實現的簡單、優雅,可靠性有保證。

同時 Tribenode 有些不足的地方:

  • Tribenode 必須以 Clientnode 加入到每一個 Elasticsearch 集羣,Master 的變動任務必須等待 Tribenode 的迴應才能繼續,可能影響到原集羣的穩定性。

  • Tribenode 不會持久化 ClusterState 對象,重啓時須要從每一個 Elasticsearch 集羣獲取元數據。

    而在獲取元數據期間,Tribenode 就已經可以提供訪問,會致使查詢到還在初始化中的集羣索引訪問失敗。

  • Tribenode 鏈接的集羣多了,初始化會變得很慢。針對該缺陷,咱們平臺在重啓某個 Tribenode 集羣時,將 Gateway 訪問該集羣的所有流量切到備份 Tribenode 集羣解決。

  • 若是多個集羣有相同的索引名稱,Tribenode 只能設置一種 Perfer 規則:隨機、丟棄、Prefer 指定集羣。這可能帶來查到不符合預期的異常。

  • 滴滴 Elasticsearch 平臺經過統一管控索引,避免了同一個索引名稱出如今 Tribenode 鏈接的多個集羣中。

正是 Tribenode 有了這些瑕疵,Elasticsearch 在高版本引入了 Cross ClusterSearch 的設計,Cross Cluster 不會以節點的形式鏈接到其餘集羣,只是將請求代理。

目前咱們還在評估 Cross Cluster 的方案,這裏不展開介紹。

多集羣架構拓撲

最終改造後,咱們的集羣架構拓撲以下:

 

 

按照不一樣的應用場景,平臺將 Elasticsearch 集羣劃分紅四種類型:Log 集羣、Binlog 集羣、文檔數據集羣、獨立集羣。公共集羣通常最多 100 臺 Datanode 爲基準組成一個集羣。

咱們利用滴滴雲實現了集羣的自動化部署和彈性擴縮容,能夠很方便的水平擴展集羣。

Elasticsearch 集羣前面是多組 Tribenode 集羣,主要是爲了解決 Tribenode 的穩定性問題。

Gateway 會同時鏈接 Tribenode 集羣和 Elasticsearch 集羣,根據應用訪問的索引列表,配置應用訪問的集羣名稱。

Gateway 根據集羣名稱,將請求代理到指定集羣訪問,若是訪問的是 Tribenode 集羣,則該應用能夠訪問到多個集羣的索引。

Admin 服務則管控了全部的 Elasticsearch 集羣,以及索引和集羣的對應關係。一系列功能都針對多集羣作了改造。

Sink 服務已經從 Elasticsearch 平臺分離出去,成立 DSink 數據投遞平臺。

DSink Manager 負責管理 DSink 節點,DSink Manager 從 Elasticsearch Admin 服務獲取索引的元數據信息,下發給對應的 DSink 節點。

多集羣架構實踐總結



多集羣架構收益

Elasticsearch 多集羣架構改造給 Elasticsearch 平臺帶來了以下收益:

  • Elasticsearch 平臺的隔離性能夠從物理節點級別上升到 Elasticsearch 集羣級別。對於核心的線上應用,可使用獨立的 Elasticsearch 集羣支持。

  • 不一樣類型的數據按集羣劃分,避免相互影響,減少了故障的影響面,對平臺穩定性帶來極大的提高。

  • Elasticsearch 平臺的擴展能力進一步提高,經過新增集羣能夠很好的作到水平擴展。

  • 多集羣架構最終作到了對業務方無感知,業務看起來,Elasticsearch 平臺就像一個無限大的 Elasticsearch 集羣,而無需感知索引真實的集羣分佈。

多集羣架構實踐經驗

滴滴 Elasticsearch 平臺多集羣的架構已經演進了一年半時間,這期間也遇到一些多集羣架構帶來的挑戰。

①Tribenode 穩定性挑戰

隨着集羣數量愈來愈多,前面提到的 Tribenode 不足愈來愈明顯,好比初始化的時間愈來愈長等等。

咱們採起的應對策略是部署多組 Tribenode 集羣,有幾組鏈接全量的集羣,互爲災備,有幾組只鏈接核心的一些集羣,用做更爲重要的跨集羣訪問場景。

Tribenode 的 ClusterState 元數據包含了太多的索引和 Shard,Elasticsearch 的 Search 邏輯在有些 Case 處理下容易出現耗時過長的狀況。

Elasticsearch 在 Client 接收到 Search 請求時,是在 Netty 的 IO 線程中完成請求轉發給每一個 Shard 的,低版本的 Elasticsearch 尚未限制一次 Query 的 Shard 數量。

在一些複雜的模糊索引匹配 Shard 的邏輯中,以及給每一個 Shard 發送 Query 請求時,會出現較高的耗時,可能有超過 1-2s 的 Case,這會影響到該 Netty Worker 上的其餘的請求,形成部分響應飆高的狀況。

咱們優化了 Tribenode Search 流程中一些索引、Shard 膨脹以後的耗時邏輯,解決了該問題。

②多集羣配置、版本統一的挑戰

在只有一個集羣的時候,平臺只用維護一份集羣的配置和版本。當集羣數量增多後,不一樣集羣間的 _cluster settings 信息會出現部分差別。

這些差別,可能會致使集羣間的負載不均,恢復速度過快或者過慢等問題,每一個集羣還有一份基礎的索引模板配置,這裏面也出現了部分差別。

這個問題目前咱們還在解決中,咱們計劃將 Admin 服務分離成索引管理服務和集羣管理服務,集羣管理會專一於集羣版本、配置、部署、擴容、監控等方面對 Elasticsearch 集羣進行更全面的管控。

咱們作的一些 Elasticsearch 源碼優化,會前後在部分集羣上線,這樣致使了集羣間的版本混亂的問題。

咱們的解決方案是在 Elasticsearch 和 Lucene 內增長內部的版本號,經過公司內部的發佈系統,發佈 Elasticsearch 的更新,後續集羣管理服務會將集羣的版本管理起來。

③多集羣間容量均衡的挑戰

咱們主要從跨集羣索引遷移和容量規劃解決集羣間容量均衡的挑戰,在單 Elasticsearch 集羣的時候,數據遷移能夠依賴 Elasticsearch 的 Rebalance 能力完成。

在使用多集羣架構後,平臺內部的 Elasticsearch 集羣會出現資源分配不均的問題。

例若有些索引容量增加的很快,致使所在集羣的資源緊張,有些索引數據減小,不須要佔用太多資源,致使集羣資源空閒。

因而產生了索引跨集羣遷移的需求。針對這個需求,咱們經過給索引添加版本號,解決了索引跨集羣遷移問題。以後咱們有文章會詳細的介紹該方案。

滴滴 Elasticsearch 平臺實現了索引容量的自動規劃,解決了集羣間的容量均衡。

Elasticsearch 平臺能夠動態的規劃索引的容量。當一個集羣容量規劃不足時,平臺能夠動態的遷移一部分索引到空閒的集羣中。

新的索引接入需求會優先接入在空閒的集羣資源中。滴滴 Elasticsearch 平臺是如何實現索引容量的自動規劃,也請期待後續的分享。

總結

滴滴的多集羣架構,最初是爲了解決 Elasticsearch 單集羣架構的瓶頸。爲了支持多集羣架構,後面的不少組件都須要考慮鏈接多個集羣的場景,給平臺架構帶來了必定的複雜性。

可是多 Elasticsearch 集羣帶來的穩定性和隔離性的提高,它所帶來的收益遠遠大於架構的複雜性。

改形成多集羣架構後,咱們扛住了 Elasticsearch 平臺規模爆炸式增加,Elasticsearch 平臺的規模翻了 5 倍多,多集羣架構很好的支撐了業務的快速發展。

做者:魏子珺

編輯:陶家龍、孫淑娟

出處:轉載自微信公衆號:滴滴技術(didi_tech)

版權申明:內容來源網絡,版權歸原創者全部。除非沒法確認,咱們都會標明做者及出處,若有侵權煩請告知,咱們會當即刪除並表示歉意。謝謝。

乾貨分享

最近將我的學習筆記整理成冊,使用PDF分享。關注我,回覆以下代碼,便可得到百度盤地址,無套路領取!

•001:《Java併發與高併發解決方案》學習筆記;•002:《深刻JVM內核——原理、診斷與優化》學習筆記;•003:《Java面試寶典》•004:《Docker開源書》•005:《Kubernetes開源書》•006:《DDD速成(領域驅動設計速成)》•007:所有•008:加技術討論羣

相關文章
相關標籤/搜索