出品 | 滴滴技術
做者 |魏子珺node
Elasticsearch 是基於 Lucene 實現的分佈式搜索引擎,提供了海量數據實時檢索和分析能力。Elastic 公司開源的一系列產品組成的Elastic Stack,能夠爲日誌服務、搜索引擎、系統監控等提供簡單、易用的解決方案。mysql
滴滴 Elasticsearch 簡介
滴滴2016年初開始構建Elasticsearch平臺,現在已經發展到超過3500+Elasticsearch實例,超過5PB的數據存儲,峯值寫入tps超過了2000w/s的超大規模。sql
Elasticsearch在滴滴有着很是豐富的使用場景,例如線上核心的打車地圖搜索,客服、運營的多維度查詢,滴滴日誌服務等近千個平臺用戶。restful
超大的規模和豐富的場景給滴滴Elasticsearch平臺帶來了極大的挑戰,咱們在這期間積累了豐富經驗,也取得了一些成果。本文給你們分享下滴滴在Elasticsearch多集羣架構的實踐。架構
單集羣架構瓶頸
介紹單集羣架構瓶頸前,先來看下滴滴Elasticsearch單集羣的架構。app
滴滴Elasticsearch單集羣架構jvm
滴滴在單集羣架構的時候,寫入和查詢就已經經過Sink服務和Gateway服務管控起來。elasticsearch
| Sink服務
滴滴幾乎全部寫入Elasticsearch的數據都是經由kafka消費入到Elasticsearch。kafka的數據包括業務log數據、mysql binlog數據和業務自主上報的數據,Sink服務將這些數據實時消費入到Elasticsearch。tcp
最初設計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看起來是p2p架構,但實際上,仍然是中心化的分佈式架構。整個集羣只有一個active master。master負責整個集羣的元數據管理。集羣的全部元數據保存在ClusterState對象中,主要包括全局的配置信息、索引信息和節點信息。只要元數據發生修改,都得由master完成。
Elasticsearchmaster的任務處理是單線程完成的,每次處理任務,涉及到ClusterState的改動,都會將最新的ClusterState對象publish給集羣的所有節點,並阻塞等待所有節點接受到變動消息,處理完變動任務後,才完成本次任務。
這樣的架構模型致使在集羣規模變大的時候出現很嚴重的穩定性風險。
針對這些問題,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適用的業務場景差別特別大。
這些場景各異,穩定性、性能要求各不相同的場景,一個Elasticsearch集羣即便使用各類優化手段,很難所有知足需求,最好的方式仍是按業務場景劃分Elasticsearch集羣。
多集羣挑戰
正是單集羣面臨了很是大的穩定性風險,咱們開始規劃多集羣的架構。咱們在設計多集羣方案的時候,指望對業務方是零感知的。
寫入仍是通過kafka,Sink服務能夠將不一樣topic的數據入到不一樣的Elasticsearch集羣。查詢繼續經過Gateway服務,並且業務方仍然像以前同樣傳遞索引名稱,而無需感知到平臺內部的索引分佈。全部的索引在不一樣集羣的分佈細節,均由Gateway服務屏蔽。
整個改造最大的挑戰在於查詢方式的兼容。Elasticsearch查詢索引的方式很是靈活,能夠支持*號做爲通配符匹配。這樣一個索引query可能查詢的是多個索引,好比有以下3個索引:
使用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介紹
通過調研,咱們發現Elasticsearchtribenode特性能夠很好的知足多集羣查詢的特性。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只能設置一種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平臺多集羣的架構已經演進了一年半時間,這期間也遇到一些多集羣架構帶來的挑戰。
tribenode穩定性挑戰:
多集羣配置、版本統一的挑戰:
多集羣間容量均衡的挑戰:
總結滴滴的多集羣架構,最初是爲了解決Elasticsearch單集羣架構的瓶頸。爲了支持多集羣架構,後面的不少組件都須要考慮鏈接多個集羣的場景,給平臺架構帶來了必定的複雜性。可是多Elasticsearch集羣帶來的穩定性和隔離性的提高,它所帶來的收益遠遠大於架構的複雜性。改形成多集羣架構後,咱們扛住了Elasticsearch平臺規模爆炸式增加,Elasticsearch平臺的規模翻了5倍多,多集羣架構很好的支撐了業務的快速發展。