看着圖 1 你們可能會感到熟悉,又或者會以爲部分有些陌生,這是一張聚集了目前大數據生態下大多數成熟組件的架構圖。衆所周知,大數據生態很複雜,對於我的來講,要所有學會可能要花費好幾年時間。而對於企業來講,要最大程度發揮其價值,構建一個成熟穩定、功能多樣的大數據平臺,期間花費的時間以及人力成本着實難以估量,更況且還須要考慮持續維護的問題。這就是七牛的Pandora大數據平臺靈感的來源,咱們構建一個大數據平臺,做爲產品提供給用戶,快速幫助用戶挖掘數據價值。android
七牛是以雲存儲起家的公司,平臺上有着大量的數據、業務日誌以及運維監控數據,基於對這些數據的管理以及分析的需求,Pandora誕生了。咱們搭建了一個可靠的大數據平臺,將大數據生態中的各個組件配套成一個體系發揮做用,用來解決實際業務中碰到的繁瑣、複雜、多樣化的問題。這個大數據平臺的工做從數據的採集便已開始,經過一條數據總線,再根據業務需求分流到不一樣的下游產品,從存儲到數據可視化,從實時的數據變換到離線的算法分析,咱們構建一個全棧的大數據分析產品。ios
與此同時,咱們在大數據平臺之上構建了業務工做流的概念,讓用戶只需關心構建符合他們業務模型的工做流,而無需具有大數據技術背景。不只大大下降了用戶挖掘大數據價值的成本,更爲重要的是去除了大數據技術門檻,使得各行各業的專家能夠更好的施展本身對業務的深度理解。git
在工做流上,用戶不只能夠清晰的監控本身的數據流動,輕鬆構建各種實時、離線的數據變化與自定義計算,還能夠按需彈性擴容、快速調度雲端資源,下降了運維的成本。與此同時,咱們集成了社區中大量的優秀開源軟件,對其進行優化及定製,一方面以便發揮其更強大的功能,另外一方面,也讓熟悉使用這類開源軟件的用戶能夠作到快速遷移,無縫切換使用。github
那麼,Pandora究竟是一個怎樣的平臺呢?工做流又是怎樣的呢?讓咱們首先來直觀的看一下工做流的使用形態,如圖 2 所示。
算法
最左邊的數據源是工做流的起點,數據源能夠是一個,也能夠是多個。在實時計算的工做流中,咱們只能有一個數據源,這個數據源就是數據收集匯聚的中心,也能夠理解爲數據總線,全部不一樣終端的數據打向數據源,再經過數據源根據業務需求分發到不一樣下游;在離線工做流中,咱們能夠有多個數據源,不一樣的數據源表明的是存儲在不一樣地方的離線數據,能夠是七牛雲存儲中的不一樣文件,又或是HDFS等不一樣類型的數據倉庫。數據庫
無論是實時仍是離線,從數據源開始,你就能夠根據須要作不一樣類型的處理。後端
最基本的處理是對數據進行一些定製化的計算,好比你可能須要對天天海量的數據進行一個定時分析匯聚的功能,計算每分鐘有多少條數據、每小時有多少條數據,從而縮減數據規模節約存儲成本,或者從中生成一份數據日報、週報等等;又好比在這個信息爆炸的時代,你從網上抓取了海量的數據,須要對數據進行一些清洗、過濾、刪選,以此分析社會熱點或其餘有價值的信息;又好比你想對數據作一個延伸或擴展,最多見的就是對一個IP獲取它的運營商、所在區域等信息。那麼你就能夠建立一個計算任務,最簡單的編寫一些SQL語句就能夠作數據變換;進階一些的使用方式就是編寫一些UDF(用戶自定義的函數),作一些較爲複雜的變化;更高階的就是直接編寫一類插件,直接使用大量Java的類庫對數據進行操做。固然,在離線計算中,除了單個數據源的計算任務之外,你還能夠對兩個數據源,亦或是兩個計算任務的結果進行聚合,而後再進行計算等等。計算任務能夠知足你對於整個工做流的完整數據處理需求。api
在進行過一個基本的計算之後,可能最多見的一個需求就是對這些計算後的數據進行檢索,直白的說就能夠查詢你的數據。那麼你能夠建立一個導出到日誌檢索,在這裏你就能夠搜索你的計算結果。固然,你的數據在數據源中也徹底能夠不通過任何計算任務,直接導向日誌檢索。又或者你但願對數據進行更完善的實時監控和數據可視化處理,那麼就能夠導出到時序數據庫,針對帶有時間戳的數據作高性能數據寫入和查詢優化,知足你針對實時海量數據的即席查詢需求。七牛雲存儲
另外一方面,你工做流計算後的結果,能夠直接再次導出到七牛雲存儲進行永久保存,或者與後續的數據結合進行分析。你也能夠理解爲經過大數據服務,七牛的雲存儲變成了一個數據倉庫爲客戶提供服務。以前已經存儲在七牛雲上的數據(如CDN日誌等),徹底能夠直接使用咱們的大數據平臺進行計算,無需任何接入過程。緩存
爲了方便用戶充分利用本身的數據,咱們甚至提供了導出到 HTTP 服務,用戶能夠構建本身的 HTTP 服務器來接受通過Pandora大數據平臺計算後的數據。
圖 3 是 Pandora的產品架構圖,基本的功能在第 2 節中均已介紹,在此再也不贅述,在講解系統架構以前,讓咱們對照產品架構進行一些基本的系統組件技術名稱的對照說明,以便下文描述簡潔便於理解。數據經過咱們提供的數據上報工具logkit、各種SDK或者用戶直接調用開放API接入,數據進入後不管是數據源自己仍是通過計算任務後的臨時數據存儲節點,咱們都一稱做消息隊列,技術上稱之爲Pipeline,像不一樣下游提供導出服務的組件咱們稱之爲Export,在Pipeline中承擔各種計算任務處理的組件咱們稱之爲Transform,下游的時序數據庫服務咱們稱之爲TSDB,下游的日誌檢索服務咱們稱之爲LogDB。
有了這些基本概念後,讓咱們對照圖 4 Panora系統架構圖,開啓咱們的Pandora架構演進之旅。
最左側的組件是數據收集的部分,數據來源於客戶各類各樣的系統。相信大部分用戶在接入大數據平臺時,都會面臨數據收集這一難題,一方面但願數據不重不漏所有收集上來,一方面又要數據收集儘量高效且不太消耗機器的各種資源,同時還要知足場景各異的不一樣狀況下的數據收集需求。熟悉這塊的朋友可能也早已瞭解,社區已經有不少不一樣類型的開源數據收集工具,知名的包括flume、logstash、fluentd、telegraf等等,他們各有利弊,功能上大都知足需求,可是在性能上和一些非通用需求的場景上不盡如人意。爲了更好的知足用戶不一樣類型的需求,咱們自主研發了一個能夠收集各類各樣數據源數據的工具logkit,圖 5 是logkit的功能架構示意圖。logkit使用go語言編寫,以插件的形式定製不一樣的數據收集解析需求,處理高效、性能損耗低,同時也已經開源,咱們很是歡迎你們一塊兒參與到logkit的使用和代碼開發定製中來,爲logkit 提提PR,固然,也很是樂意接受您關於logkit的任何意見或建議,只需在github提issues便可。
有了這樣一款數據收集工具,幾乎 90% 的數據收集場景咱們已經解決了,可是還會有諸如ios、android客戶端數據直接上報、頁面請求點擊數據直接上報等需求,爲此咱們提供了各種語言的SDK方便用戶使用,以彌補logkit功能上沒法知足的需求。
數據收集上來後,就正式進入咱們的Pandora大數據平臺了。全部上報的數據不管最終是否計算或存儲,都會統一暫存進入咱們的大數據總線Pipeline。相信通過上面的介紹,不少讀者早已發現,Pandora幫助用戶根據不一樣場景選擇最適合的大數據分析方式。而這套模式的核心,毋庸置疑,就是處理數據在不一樣大數據產品間的流轉。
Pipeline就是這樣一條數據總線,在數據總線的基礎上咱們打通一條條管,根據所需的場景導出到後端相應的存儲服務上。同時據此來進行資源分配和任務管理。這樣一來,就能夠避免用戶技術選型及技術架構與使用姿式和業務場景不匹配的狀況,同時也能夠利用雲計算的優點,按需分配、快速擴容。
如圖 6 所示是咱們的初版架構,實現上咱們經過定製開源版本的confluent,並把它做爲咱們這個架構系統的核心。數據要流入系統,咱們首先構建了一個 Points Gate(API 服務器),Points Gate 解析校驗用戶的數據格式並調用confluent中kafka-Rest提供的rest API 將數據寫入到kafka,利用schema-registry完成數據格式的校驗以及數據解析,經過kafka得到數據管道的能力。
在進行元數據建立時,咱們的調度器在元數據服務器上建立一個用戶元數據存儲在MongoDB當中。對於MongoDB的元數據訪問,咱們構建了一個二級緩存系統(即圖中qconf),數據在進入或者導出時都會經過二級緩存訪問元數據,這樣數據就能夠快速獲得校驗,扛住海量的數據吞吐。Kafka自己包含了Zookeeper組件,咱們也藉此來保證總體系統組件的服務發現以及數據一致性這兩個問題。
然而,隨着應用的增長,數據量愈來愈大,這樣,單個定製版的 Confluent 並不能知足這些數據量增加的業務壓力,以及用戶不斷增長的場景需求。kafka topic(partition)不斷增加致使總體響應變慢,沒法快速切換災備等待問題日益凸顯。在這個基礎上,咱們對本來的系統架構進行了調整。
3.2.2 Pipeline的升級
如圖 7 所示,咱們對Pipeline的第一次總體升級包含了大量的組件基礎架構的調整。首先咱們構建了Confluent的多集羣系統,將單個Confluent集羣規模控制在100臺機器之內,分區數量控制在1萬之內,根據需求對集羣進行路由。
可見經過多集羣系統,咱們能夠合理控制每一個confluent集羣的規模,同時根據咱們的調度器按照須要切換用戶到不一樣的集羣上,實現快速切換、擴容、容災、隔離等調度需求。
其次咱們對Points Gate、Transform、Export中無狀態組件進行了容器化處理,利用咱們七牛內部的容器雲平臺,實現了無狀態服務的快速部署、擴容以及灰度發佈等需求。
此次架構的調整效果顯著,咱們成功抗住了天天上百TB,千億級數據點的數據增量。
不止於此,爲了更高的性能提高以及節約成本,咱們在上述升級以後進行了第二次的架構升級。此次升級主要體如今對Confluent的進一步定製(或者說替換),咱們再也不使用kafka-rest,同時對打點的數據格式進一步優化,又一次節約了近一半的機器成本。
在解決了數據總線問題之後,問題的重中之重天然是如何處理數據導出的問題。衆所周知,數據導出其實就是從一個上游系統拉取數據,而後將數據再發送到下游系統的過程。但這裏面涉及的難點和調整可能大多數都是鮮爲人知的了。在介紹咱們的導出服務架構以前,很是有必要描述一下針對海量數據導出,到底有哪些挑戰?
3.3.1 數據導出的挑戰
首先面對的第一大挑戰天然是高吞吐量的問題,海量數據不斷涌入帶來的必然問題就是網卡和CPU分配的問題,一旦流量分配不均,就會出現大量因網卡、CPU負載太高帶來的延遲,嚴重影響服務可用性。
顯然,保證低延遲就是第二個挑戰,一旦各個鏈路有一個環節配合不均衡,就會帶來大量延遲,如何保證導出的上下游始終保持較高的吞吐量,從而保證較低的延遲,是一個很是大的調整。
爲了保證低延遲,就要更好地適配多種下游,使其始終保證高吞吐,瞭解下游不一樣服務的特性,並針對這些特性動態的調整資源,亦是一個很大的挑戰。
除此以外還有分佈式系統的常見問題,須要保證服務高可用,以及水平擴展的能力。保證任務單元標準化,任務粒度能夠切分擴展;保證調度任務節點故障不影響其餘節點的正常導出等等。
最爲重要的是自動化運維,當導出的任務涵蓋數十上百臺機器後,人力已經沒法精細化處理每臺機器的任務分配,資源必須能夠自動調度、調整以及構建統一的任務監控。
3.3.2 導出服務功能介紹及架構演進
]讓咱們來看一下導出服務的功能架構圖,如圖 8 所示。咱們的導出服務主要涉及三個層級,一個是元數據管理,在這一層保證任務的分配以及監控展現;第二層則是任務管理層,除了基本的任務切分、併發管理以及通訊協議以外,還包含了壓力預估模塊,根據以前的數據量預估下一階段的數據流量,從而調整資源分配;再下一層則是數據處理層,在這一層完成諸如數據預取、數據校驗、壓縮以及推送到下游等任務。
在最初的版本中,咱們會在 zookeeper 上面建立一個任務(task) ,Export 經過分佈式鎖對task進行爭搶,被搶到的任務則開始直接導出,如圖 9 所示。
在這樣一個初步架構中,咱們基本完成了水平擴展以及高可用的需求,同時作了諸如數據預取,延遲報警、數據監控等多種功能和優化。可是流量上來之後,很容易出現某個機器爭取的任務流量變大,致使大量數據打到同一臺機器上,致使網卡和CPU負載太高,延遲急劇升高。本質上就是流量分佈不均勻,致使導出性能低下,機器資源的平均利用率也低。
此時,咱們對該方案進行第一次架構升級,如圖 10 所示。咱們將原來topic級別的任務按照parition進行分佈式消費。爲了使得每一個partition粒度的任務大致是均等的,咱們將partition承載的數據量按照標準化處理,並根據歷史流量進行預測,預測結果超過當前咱們定製的標準符合的對應容量即觸發擴容,這樣的標準化有效簡化了調度的難度。
同時咱們將原來純粹的export改成master/worker結構,Master對收集到的任務進行主動權衡分配,根據任務的歷史流量進行流量預測、對任務的partition數量、每一個export worker的機器資源剩餘狀況,進行綜合調度。對於一些特殊任務作機器黑白名單綁定等功能。
在作了上述工做之後,咱們機器的總體利用率有了很大的提高,可是因爲下游系統的不一樣,寫入吞吐量始終良莠不齊,沒法始終保持在一個較高的水平。爲了解決該問題,咱們再次對架構進行小範圍升級,如圖 11 所示,咱們在導出的export worker端增長了一套對下游系統的適配加速模塊。其核心思路就是按照下游的吞吐能力進行自動調節請求體大小以及併發度。這個主要是爲了解決上下游傳輸數據速度不匹配,以及下游吞吐量不穩定的問題。
相似於Flume的思想,咱們構建了一個內存隊列,以事務的形式從隊列中獲取數據(或者失敗回滾),根據下游的狀況調整單次數據請求的大小和併發度,以及調整出錯等待時間等。這樣一來,整個導出的吞吐量就能夠頗有效的進行控制,去除了毛刺,極大的提升了機器資源的使用率以及導出效率。
解決了數據的導出問題,基本上絕大部分數據流轉的問題也都解決了。下面咱們開始關注Pandora下游的一系列服務。
TSDB是七牛徹底自主研發的分佈式時序數據庫服務。TSDB針對時序數據定製存儲引擎,根據時序數據帶有時間戳的特性,咱們針對時間戳作特殊的索引,實現數據高速匯入和實時查詢獲取的能力;同時構建了簡單且高性能的HTTP寫點和查詢接口,爲查詢聚合數據量身定製了類SQL語言,徹底兼容開源社區InfluxDB的API,支持無縫對接到Grafana,對數據進行高比例壓縮,實現低成本存儲。除此以外,TSDB擁有開源社區版本的InfluxDB所沒有的分佈式、多集羣、高可用,水平擴容、以及分庫分表能力。
如圖 12 所示,TSDB是咱們基於tsm構建的分佈式時序數據庫,擁有每秒60萬條記錄的寫入性能以及實時查詢聚合分析的能力。在分佈式方面,除了基本的多集羣、多租戶隔離的概念之外,咱們還針對性的作了兩個強大的擴容功能,一個是根據時序進行縱向集羣切割,解決海量數據寫入時磁盤的快速擴容問題;另外一個則是根據用戶的標籤進行數據庫表橫向切割,相似傳統數據的分庫分表能力。在進行了這兩大擴展能力變換後,數據的寫入和查詢依舊高效,甚至查詢速度在分庫分表後性能有所提高。
爲了實現這樣的擴容功能,咱們基於此構建了一個分佈式計算引擎,解析用戶的SQL並變成一個個執行計劃,將執行計劃下推至不一樣的TSM計算引擎實例中進行計算,最後再進行數據reduce計算反饋給用戶。
除了數據寫入性能高之外,還支持數據即時查詢,數據寫入成功便可查詢,數據零延遲;同時支持InfluxDB的持續聚合功能,相似於定時任務同樣將持續寫入的數據不斷進行聚合計算;當單個用戶數據量過大時,擁有橫向拓展能力,集羣擴展後寫入性能不打折,查詢效率更高。針對時序數據的特性,咱們將數據進行冷熱分離, 對數據按照時間分片,使最近的數據查詢性能更高。
在瞭解完咱們的時序數據庫之後,讓咱們來看一下下游的另外一大服務,日誌檢索服務,又稱LogDB。日誌搜索實際上是幾乎全部技術開發人員都會須要的服務,傳統解決方案(ELK,Elasticsearch、Logstash、Kibana) 針對小數據量不會出現任何問題。可是當數據量過於龐大時,這些方案也就不那麼適用了。
咱們LogDB的底層能夠經過插件的形式接入不一樣類型的搜索引擎,包括Solr、Elasticsearch(簡稱ES)等,目前承載海量數據搜索任務的底層引擎主要使用的是ES。與單純的使用ES不一樣,LogDB自己是一套分佈式系統,管理的單元能夠是一個ES節點,也能夠是一個ES集羣,因此咱們構建了大量的ES集羣,不一樣的集羣用以適配不一樣的用戶以及不一樣的搜索需求。
大致上咱們將搜索的需求分爲兩類,一類是ELK類需求,針對如程序運行日誌、業務訪問日誌等收集索引,這類需求的廣泛特色是數據量大,時效性高,帶有時間戳,無需存儲太長時間,無需更新;另外一類需求相似於搜索引擎,數據存在更新須要,且強依賴於不一樣類型的分詞器,數據冷熱不明顯,不帶有明顯的時間屬性,咱們稱之爲通用檢索需求。這兩類需求,LogDB都是徹底支持的,可是針對這兩類需求,咱們作的優化不一樣。
在咱們討論具體的優化以前,讓咱們先來看一下LogDB的架構圖, 如圖 13 所示。首先是數據的寫入,LogDB是Pandora平臺下游服務,上游主要是以前提到的Pipeline以及Export。Export導出的數據經過apisever將數據導入到不一樣的ES集羣當中,根據不一樣用戶的需求給他們提供不一樣的集羣服務,集羣之間也能夠相互進行切換。
那麼如何確認數據到底數據哪一個集羣呢?爲了使得海量的數據快速確認,咱們對元數據進行了多級緩存,包括MongoDB的實際存儲、memcached的二級緩存,以及本地的緩存,極大提升了數據校驗的速度。除此以外,LogDB自己也是Pandora的用戶,使用了TSDB對自身數據進行監控,使用七牛雲存儲進行數據快照與備份。同時將計費數據導出到雲存儲,利用咱們的XSpark機器進行離線計算。
架構中剩下的部分都是咱們針對不一樣索引作的優化。簡而言之,咱們首先構建了一個高性能隊列,可讓外部的數據持續高吞吐寫入;同時咱們還會根據歷史流量進行動態索引平衡、不一樣集羣的索引跨集羣平衡、索引定時清理、VIP集羣隔離等功能;而且會對 ES 的搜索進行分步搜索控制,緩存歷史搜索,優化用戶搜索的效率和體驗等等.
最後有讀者看到這裏,也許會忍不住想問,若是隻是純粹的想使用一個高度靈活的Spark集羣,不但願通過Pandora各種複雜的計算、導出,甚至數據都沒存儲在七牛,可不能夠享受七牛的Spark大數據服務呢?是的,徹底能夠,這就是咱們的XSpark!
XSpark不只與Pandora總體徹底打通,能夠把七牛雲存儲當成一個數據倉庫使用,又徹底能夠獨立使用。即用戶除了在Pipeline裏面作離線計算以外,你還能夠選擇直接一鍵生成一個基於容器雲的我的專屬Spark集羣,直接讀取你本身的數據源,只要Spark支持的數據格式,XSpark都支持。若是你的數據已經存儲在七牛雲存儲上,XSpark能夠直接高效讀取並計算,XSpark是Pandora提供給大數據高端用戶的一個高度靈活的離線計算產品。
顯然,容器雲所具備的優點XSpark全都具有,你徹底能夠根據須要動態伸縮的XSpark資源數量與規格,按需啓停等等。
圖 14 是 XSpark 的架構圖。咱們將Spark的master和worker分爲不一樣的容器,首先啓動Spark的master容器,獲取master地址,而後再根據用戶的配置,啓動相應數量的worker容器,worker容器自動向master註冊。同時容器雲的支撐使得咱們的XSpark能夠在運行過程當中進行縮容擴容。
同時XSpark也開放了完整的Spark監控以及管理控制頁面,徹底兼容開源社區的Zepplin使用方式。