大數據時代,數據的重要性不言而喻,尤爲對於互聯網公司,隨着業務的快速變化,商業模式的不斷創新、用戶體驗個性化、實時化需求日益突出,海量數據實時處理在商業方面的需求愈來愈大。如何經過數據快速分析出用戶的行爲,以便作出準確的決策,愈來愈體現一個公司的價值。現階段對於實時數據的建設比較單一,主要存在如下問題:數據庫
實時流數據來源系統較多,處理很是複雜,而且不一樣業務場景對實時數據的要求不一樣,所以在建設過程主要有如下挑戰:緩存
咱們在充分梳理業務需求的基礎上,從新對實時流進行了建設,將實時數據分層建模,並對外提供統一的接口,保證數據同源同口徑;同時,在數據服務層,增長可配置信息模塊解決了配置信息不能自動化的問題,在數據處理策略上作了多線程處理、預計算、數據降級等優化,在數據安全方面增長數據審計功能,更好地提高了產品的用戶體驗。安全
產品總體建設方案基於美團技術平臺,總共分爲源數據層、存儲層、服務層及WEB層,總體架構以下所示:服務器
圖1 總體架構圖數據結構
源數據層:主要提供三部分數據,實時數據、離線數據、配置信息、維度信息。
存儲層:源數據清洗後放入相應的存儲引擎中,爲服務層提供數據服務。
服務層:提供三部分功能,數據API服務、預計算服務、權限服務、數據審計服務。
Web層:使用Echarts可視化數據。多線程
依託於美團提供的公共資源平臺,數據架構按功能分爲數據採集、數據處理、數據存儲、數據服務四層,以下所示:架構
圖2 數據架構圖併發
數據來源主要有兩種:業務上報的Log日誌及數據庫Binlog日誌。這些日誌經過美團日誌中心進行採集後存儲在消息中間件Kafka中,並按照不一樣的分類存儲在不一樣的Topic中,供下游訂閱。框架
數據處理顧名思義,就是對採集的實時流進行邏輯處理,按業務需求輸出對應的實時數據,所以這一步驟是流式計算的關鍵,分兩步進行:數據加工、數據推送。工具
數據加工:數據加工一般須要在流式計算系統中進行,目前流行的流式處理系統主要有Storm、Spark Streaming系統及Flink系統,這些系統都能在不一樣的應用場景下發揮很好處理能力,並各有優缺點,以下圖所示:
計算框架 | 吞吐量 | 延遲 | 傳輸保障 | 處理模式 | 成熟度 |
---|---|---|---|---|---|
Storm | 低 | 毫秒級 | At least once | 單條處理 | 成熟 |
Spark Streaming | 高 | 秒級 | Exactly once | 微批處理 | 成熟 |
Flink | 高 | 毫秒級 | Exactly once | 單條處理/微批處理 | 新興 |
最終咱們選擇Storm做爲實時數據處理框架,並藉助公司提供的通用組件來簡化拓撲開發流程和重複代碼編碼。例如,組件MTSimpleLogBolt的主要功能是將Kafka中讀取的數據(Log or Binlog)解析成Java實體對象;組件StormConfHelper的功能是獲取Storm做業應用配置信息。
數據推送:將處理好的數據推送到存儲引擎中。
數據加工完成後會被存儲到實時存儲引擎中,以提供給下游使用。目前經常使用的存儲引擎主要有MySQL、Druid、Elasticsearch、Redis、Tair比較以下:
存儲引擎 | 優勢 | 缺點 |
---|---|---|
MySQL | 使用簡單,支持數據量小 | 數據量大,對MySQL的壓力大,查詢性能慢 |
Druid | 數據預計算 | 不支持精確查詢 |
Elasticsearch | 查詢效率快,支持經常使用聚合操做;能夠作到精確去重 | 查詢條件受限 |
Redis | 內存存儲KV,查詢效率高 | 寫入資源有限,不支持大數據量寫入 |
Tair | 持久化和非持久化兩種緩存,查詢效率高 | 單節點性能比Redis較弱 |
Kylin | 多維查詢預計算 | 不支持實時 |
綜上比較,因爲實時數據量較大,且數據精度要求較高,所以咱們最終選擇交易存儲使用ES,流量存儲使用Druid,維度存儲使用Tair,中間數據存儲使用Redis;而離線數據,咱們採用Hive和Kylin存儲。
將存儲引擎數據統一對外提供查詢服務,支持不一樣業務應用場景。
整個數據層架構上主要分爲實時數據和離線數據兩部分:實時數據分爲交易的Binlog日誌和流量的Log日誌,通過Strom框架處理後寫入Kafka,再通過DataLinkStreaming分別寫入ES和Druid;離線數據經過Hive處理寫入Kylin。
圖3 產品數據架構
下圖所示爲一條消息的處理流程:
圖4 數據關係
兩個Topic分別是order_base(主要存放訂單基本信息:訂單id、訂單狀態、支付時間、票量、金額等);order_biz(主要存放訂單的擴展信息:訂單id、訂單類型、出發時間、到達時間、出發城市、到達城市)。咱們最終要拿到一條包括上述所有內容的一條記錄。
圖5 數據處理流程
具體例子:Bolt在處理一條記錄時,首先判斷這條記錄是base仍是biz,若是是base則寫入緩存中base的Category中,若是是biz則寫入biz的Category中。以order_id爲Key,若是是base則去和biz關聯,若是biz存在則表明可以關聯上,這時發送關聯後的完整數據,同時刪除該主鍵(order_key)記錄;若是biz中不存在,則說明沒關聯上,這時可能biz的數據延遲或者是丟失,爲了保證主數據的準確性,這時咱們只發送base的數據,緩存中的數據保留不被刪除。若是這條消息是biz,則首先會更新緩存中該主鍵的biz記錄,而後去和base關聯,關聯上則發送同時刪除base中數據,不然不發送。此時咱們會根據ES的Update特性去更新以前的數據。從現實效果來看保證了99.2%的數據完整性,符合預期。
在Topic2es的數據推送中,經過DataLinkString工具(底層Spark Streaming)實現了Kafka2es的微批次同步,一方面經過多併發batch寫入ES得到了良好的吞吐,另外一方面提供了5秒的實時寫入效率,保證了ES查詢的實時可見。同時咱們也維護了Kafka的Offset,能夠提供At lease once的同步服務,並結合ES的主鍵,能夠作到Exactly once,有效解決了數據重複問題。
在數據寫入ES過程當中,因爲數據量大,索引時間區間長,在建設索引時須要考慮合理設計保證查詢效率,所以主要有如下三點優化:
整個實時數據開發遵循大交通實時數倉的分層設計,在此也作一下簡單介紹,實時數倉架構以下:
圖6 實時數倉架構
ODS層:包含美團頁面流量日誌、模塊事件日誌以及用戶操做的Binlog信息日誌,是直接從業務系統採集過來的原始數據。
事實明細層:根據主題和業務過程,生成訂單事實和流量事實。
彙總層:對明細層的數據擴展業務經常使用的維度信息,造成主題寬表。
App層:針對不一樣應用在彙總層基礎上加工擴展的聚合數據,如火車票在搶票業務下的交易數據彙總信息。
規範建模後,業務需求來臨時,只須要在App層建模便可,底層數據統一維護。
後臺服務主要實現 登錄驗證和權限驗證(UPM)、指標邏輯計算和API、預計算服務、數據質量監控、數據審計功能。因爲數據量大且實時性要求較高,在實現過程遇到以下挑戰:
針對以上問題,下面進行一一詳述:
服務層處理數據過程當中,因爲數據量大,在查詢時須要必定的響應時間,因此在保證響應性能方面,主要作了如下優化:
圖7 性能響應優化
使用緩存避免不了出現一些問題,好比緩存失效、緩存雪崩等問題,針對緩存雪崩問題,經過設置不一樣Key的過時時間可以很好的解決;而對於緩存數據失效,咱們有本身的數據降級方案,具體方案以下:
圖8 數據降級方案
預計算數據會分別在Redis、Tair和本地緩存中存儲一份以保證查詢效率,當查詢Redis數據不存在時,會去Tair中讀取數據,Tair也爲空時,會讀取本地緩存,只有當本地緩存數據也爲空時,纔會現查ES作聚合計算,這樣也會下降ES的查詢壓力。
實時監控預警很是重要,在數據出現問題時,一方面可以及時通知咱們快速定位修復數據,另外一方面也可以及時周知業務同窗,避免作出錯誤分析。基於此,咱們作了兩方面的實時監控,其一是對源實時流在Storm處理層面的監控,確保源實時流正確生產;其二是對展現的彙總數據進行監控,確保產品展現指標數據正常。
針對數據出現問題預警,咱們在解決方案上規範了流程:
在以數據取勝的時代,數據的安全不言而喻,咱們採用公司提供的UPM權限接口進行二級權限管理並加入審計功能及水印功能,可以準確記錄用戶的全部訪問以及操做記錄,而且將日誌數據格式化到數據庫中,進行實時監控分析。
實時數據能夠爲業務特定場景分析決策提供巨大支持,尤爲對於大交通節假日及春運期間。在大交通實時戰場沙盤產品化過程當中,咱們投入了大量的思考和實踐,主要取得如下收益: