大數據平臺架構方法論、模型與實踐深度觀察

近日筆者對大數據平臺架構做了廣泛的調研,目的在於對當前的主流大數據架構的方法論、模型與實踐有一個全面的觀察,以便爲電商、出行、製造業、金融、媒體、智慧城市、物流、車聯網等各行業朋友在理論與實踐上提供一點參考,尤其以實時流式計算爲核心。

1 方法論

目前大數據架構主流的方法論有三種:

  • 2014年1月份Tweeter的Nathan Martz提出的Lambda
  • 2014年7月份Linkedin的Jay Kreps提出的 Kappa
  • 2015年Google的Tyler Akidau 等提出的Dataflow Model

這裏不轉述它們的內容,或做什麼比較,網上很容易找到相關內容,個人建議最好看鏈接指向的原文。這裏想特別指出的是,截止本文的寫作,Dataflow是最流行的模型,它不僅激勵了Apache Flink的發展,而且Dataflow模型的作者Tyler Akidau等也是Apache Beam的Founder與Commiter。Flink和Beam都實現了Dataflow模型的很多概念,它可以廣泛地應用於數據處理領域,包括ETL、數據處理的服務等,不限於批流統一。

總的來說,大數據架構的整個發展歷程可以簡單地這樣總結:首先,Lambda批流並舉、既獨立又互補;然後,Kappa倡導統一爲流;現在,Dataflow統一流、批、微批,並建立概念模型。不過Kappa只是提出了想法,而Dataflow將模型做了細化,包含了一些重要的實踐探索與概念(Operator/Window/Trigger/Accumulate/Retract/Watermark/Session),並做了具體展開。

大數據架構發展到今天,批流矛盾早在前幾年就顯現了,各大互聯網公司也早就遇到了這一矛盾。Google提出Dataflow並不是空穴來風,它也有這種矛盾,分立的流計算MillWheel和批計算FlumeJava,其實在發佈Dataflow模型之前,Google內部已然碰到了二者的矛盾問題及部分的解決。

Beam最早在2014年作爲Google Cloud DataFlow SDK發佈,在2016年捐給了ASF。Flink和Beam都得到了三個有關論文的啓發(MapReduce,MillWheel,DataFlow)。但是Beam並不是獨立的Runtime,它是通過Runner來與各種執行引擎集成的,包括:Apache Flink、Apache Spark、Apache Samza、Hazelcast Jet、Google Cloud Dataflow等。Beam支持各種語言,如:Java、Python、Go、SQL,而且還支持它們的ML庫,如:Numpy、Pandas、Tensorflow。另外,Beam以統一的API來處理流與批,而Flink是不同的API(DataSet和DataStream)。有些大公司爲平臺支持語言少或者與機器學習框架集成問題而煩惱,也許Beam是不錯的探索選項,Flink官方鼓勵Beam+Flink模式。

目前,雖然ASF的Flink、Samza、Beam都擁抱批流統一的理念,但其中,Flink實現得最爲充分、社區也最爲繁榮。

2 Ingestion

2.1 模型及原則

總要有數據才涉及到對數據的處理,所以從數據的源發地開始看看數據的攝入情況,其基本的概念模型如下:

對Figure 1中模型的要求:

Ingestion的原則:

  • 高可用、高吞吐量;
  • 限流或Backlog存儲,也許Ingestion層本身資源不足、也許下游處理不過來;
  • Connector,可自行擴展,支持多種協議與技術;
  • 有豐富的Built-in Connector,在Ingestion環節尤其看中流存儲;
  • 容量可自動伸縮,Scalability;
  • 支持主流集羣管理,如:Mesos/Yarn/Kubernetes;
  • 輕量的從Source到Sink的計算,完全可配置,計算不需要Shuffle;
  • 不丟數據,Loss Tolerant;
  • 保證送達,Guaranteed Delivery;
  • 有全面的監控、告警;
  • Auto failover;

Ingestion管理的原則:

  • 強大的UI;
  • 動態配置;
  • 策略配置,包括資源調度;
  • 安全管控的配置;
  • 發佈的版本控制與審計;
  • 集成元數據管理;
  • 身份認證、授權、多租戶;

2.2 技術推薦

基於上述模型與要求,以下按數據的源頭、實際上也是對應的Ingestion方式,分別進行分析與技術推薦。

Web page/Mobile App/MES/IoT/System Built-in Producer, 都是從公網或內網發過來的情況,是被動接收。對於這類,可能很多公司都自研了,個人倒是建議採用Apache NiFi,雖然國內有DataX,但是NiFi的能力要豐富得多。

簡單來講,可以把它想象爲一個橋樑,在企業級的全景圖中,如果想讓數據從A流到B,並在中間做些轉換可以考慮,它是系統間的自動化的數據加工管道,不需要編程,可以在可視化的環境中拖拽完成。它不僅可以連接各種主流大數據框架,而且支持基於各種協議的偵聽、讀、寫,甚至IoT的MQTT;它也支持對各種文件格式的處理,如:Parquet、CSV、JSON、Avro、ORC等,還支持各種腳本語言。

這裏之所以推薦NiFi,是因爲它已經相當成熟,有了每天處理幾十億數據的案例,雖然它也有算子構成的DAG,但是更側重兩端。多年以來它在流管理、柔性伸縮、安全、易用性、監控等方面都在不斷髮展,它最突出的一點是聲稱Loss Tolerant、Guaranteed Delivery,通過WAL和可插拔的內容庫。NiFi實在是多面手,如果要在企業系統全景圖中的構件之間架設一個輕量流式處理的橋樑,值得考慮。它可以承擔在公網上大吞吐量地接收消息的角色。雖然單純從功能上看,自研並不難,但是要綜合考慮到管理、安全、運維、監控、數據不丟失、自動故障轉移、多租戶等各個方面,需要做的工作還是很多的,所以作爲企業級大圖景在雲中的最外層構件,還是推薦這種已經有相當積累的框架。有些公司不僅有侵入式的埋點,還有非侵入式的Javaagent、APM、Pinpoint等,如果要直接通過網絡發送數據,也不妨嘗試用NiFi來接收,如果落爲文件也可以用,下面會提到。

Database,首先可以是定期增量或全量批拉的方式,這裏主要講實時的CDC方式,數據是基於CUD事件被推過來的。如果是MySQL,可以採用Canal或者用MySQL-Binlog-Connector-Java自己寫。前者有個不好的地方在於,它是分Server/Client的,用後者自己寫可以把這個邏輯寫成一個定製的NiFi Processor,然後也許需要對代碼邏輯做一些中間處理或者用NiFi界面構造DAG,最後流入Kafka,也可以同時流入其它存儲。這種方式的實時性非常高,可立即對MySQL中的CUD事件做出反應,兩種方式都需要獨特的數據庫權限。

如果是Oracle,也要求實時性,那麼Oracle GoldenGate for Big Data是一個選項,可以把Oracle中的交易變化實時地反映到各種大數據存儲中,包括Kafka。如果是PostgreSQL,也有CDC,不過Oracle和PostgreSQL都沒有內置支持。

如果HBase在一線業務應用中直接作爲存儲,可以考慮寫一個基於HBaseEndpoint的CDC(Change Data Capture)。如果是Cassandra作爲一線業務存儲,官方有CDC支持。業務數據庫的CDC環節一定要加上監控、告警的機制,實際上這兩種機制要在整個企業IT大圖景中所有的地方都加上,才能隨時感知應該知道的系統的健康狀況。對於RDBMS,如果可以接受批計算,當然傳統的Sqoop是一個選項。

System log,可以用Apache NiFi中的TailFile(支持Rolling)這個Processor,中間加上自己寫或拖拽處需要的處理邏輯,最後吐到Kafka等存儲中。或者,使用經典的Flume也是沒毛病的,但是簡單就是美,都用NiFi豈不是更好。

這麼看來,其實用NiFi一個框架就可以解決所有數據的問題了,而且,NiFi具備綜合的管理能力,如:跟蹤、監控、拖拽開發、多租戶、HA方案等。可以把NiFi看成是萬能的Integrator,但不要把複雜的計算邏輯讓它來擔當,畢竟那不是它的強項。有趣的一點是,它還有Backpressure的能力,這意味着在整個企業大數據架構的最外延、數據的入口處可以有一個控流閥來控制流速,也許在某種場景是個不錯的強項。

3 元數據管理

元數據概念起源於20世紀下半葉,廣爲傳知是在RDBMS時代。而到了當今這個數據時代,應該用更廣袤的視野來看待它,包括:

  • 傳統的RDBMS的元信息,庫、表、字段、關係、UDF、觸發器、存儲過程等;
  • 關於計算體的元信息,DC、集羣、產品、應用、系統、作業、服務、UDF、算子;
  • 關於人的元信息,地域、組織架構、人員、流程;
  • 關於網絡的元信息,如:跨交換機是有距離的,延遲是不一樣的,這部分也應當爲計算所知;
  • 關於業務的元信息,各種業務術語、過程、領域、BU、渠道等;

從價值的維度看,目前數據已經被提升到資產的高度。既然數據是資產,對它的管理就應當向財務方向看起。現代的元數據管理是構建完善高效的企業IT管理、治理體系的基石。在企業範圍內,可以這樣比喻,如果把以上所有大數據體系構成要素統一抽象爲大數據王國的公民,如果沒有元數據管理,就相當於這些公民之間沒有共同的語言,自然就會有歧義、有紛爭、有困惑、有亂象、有翻譯、有成本。其中人、組織的要素也非常重要,例如:資源的交接、權限、計費、計量、資源回收、預算、流程等都涉及。企業Digital Twin的運行也離不開元數據管理。車同軌、書同文、行同倫,天下大治期矣。

本文之所以這麼早進入元數據章節,是認爲它發揮作用應該越早越好,所以就放在了Ingestion之後,其實在Ingestion階段,就應當做些必要的元數據方面的工作了。在數據進入整個企業大數據體系邊界,就應當把該做的事情做了,不論是否爲結構化數據,至少要先登記造冊,哪怕是扔到數據湖裏,如:

  • 什麼時候到的;
  • 屬於哪個業務領域、哪個部門的數據;
  • 來自哪個系統、哪個應用;
  • 基本度量;
  • Schema;
  • Format;

元數據管理涉及到數據治理、Lineage、監控、作業、業務信息、訪問控制、審計、合規、可視化、數據標準、數據質量、版本控制、計算作業、發佈管理、計量計費、告警等方方面面。它關係到企業如何有序地、高效地、穩定地、彈性地、智能地運行。雖然Haddop生態基本上用HCatalog來存儲元數據,但僅僅存儲是不夠的,對於整個企業而言是非常侷限的。一個字段名及其語義標籤在一個企業中存在多種表達,而內容本質上卻是一個,這不是什麼稀奇的事。

在企業數據的大圖景中,遠不止純粹數據層面的元數據信息需要整合管理,還包括各種其它對象,如UDF(Kylin、Hive、Flink、Spark、Storm、Phoenix等)、作業(Flink、Storm、Spark等)、部門、人員、數據中心、集羣、業務要素等,這樣才能更充分、高效、系統、完整地保障企業的運行效率。對於作業,更理想的開發和使用方式應當是配置的、聲明式的,而剩下的事情交由平臺完成,這樣才能使用戶以更加一致的、統一的、低成本的、可追溯的方式來執行所需的計算任務,而這離不開針對作業的元數據管理。因此,有一個獨立的、統一的元數據管理平臺是上策。

3.1 技術推薦

Apache Altas也許是一個不錯的起步選項,它是針對Hadoop生態的元數據管理工具,以基於HBase的GranusGraph作爲存儲,Solr用作搜索,用Hook感知Hive/Kafka/HBase/Storm/Sqoop的元數據的變化,遺憾的是沒有Flink和Pulsar,不過可以定製。Altas支持HA。

Atlas用Type/Entity模型來組織所有的元數據對象,它們的關係相當於OOP中對應的Class/Instance。Type可以分爲多個Metatype:Metatype/Enum/Collection(Array,Map)/Composite(Entity, Struct, Classification, Relationship),Composite可以有多Attribute,而Attribute可以指向Metatype從而建立豐富的關係,有趣的是Entity和Classification是可以繼承關係的,真正存放元數據信息的叫Entity,例如:一張Hive表。Atlas可以從Kafka收到關於Entity和Classification上的CUD事件。

Atlas還提供了REST API來從Atalas查詢和搜索Entity、Lineage、關係、Type信息,也可以對元數據做CUD操作,某種場合下這在各種流計算的算子中是非常有用的。Atlas用JanusGraph管理豐富的元數據對象之間的關係。

業務元數據這樣組織的,核心叫Term,一個Term可以屬於多個Category,而Category是Hierarchical的,一個Term還可以關聯多個Entity,一個Term還可以有多個Classification,Term之間還可以建立豐富的關係,如:反義詞、同義詞等。Glossary是顆粒度最大的,它下面有Term和Category。

安全方面,支持雙向SSL、SPNEGO-based HTTP(Simple/Kerberos)、JAAS(Kafka需要);Authentication支持LDAP、Kerberos等幾種方法;Authorization,可以針對在Metatype上的CUD操作、Entity上的CRUD操作,可以插件方式定製自己的授權組件,除了默認的Simple Authorizer,還可以用Apache Ranger來作爲Authorizer,Ranger是爲Hadoop生態提供的綜合的數據安全管理框架,突出裨益在於集中管理、審計用戶的訪問行爲和授權管理行爲,其模型爲Role/Attribute Based Access Control,支持各種策略。

4 流存儲

4.1 模型及關注點

Dataflow模型需要一個相應的存儲系統來支撐,流存儲的基本概念模型如下:

流存儲的核心能力是分佈式的、流式的高速讀寫,這是流計算在存儲上的必然要求。其它特徵要求就不費周章了,也基本上名釋其義,粗略理解還是可以的,可以結合自身的生產實踐來從架構上作參考。

從實踐的角度看,不管具體採用何種技術甚至自研,應當注重以下方面的投入:

容量的伸縮(Scalability)

好多大公司都在這方面遇到過挑戰。數據如何做到整體分佈儘可能均衡,一個topic還罷了,很多個怎麼辦?最好有一個全局範圍的、不影響讀寫的、自動的Rebalance。不論方式如何,有一個原則不能變,一個存儲文件中不應當存在1個以上的Topic,否則順序讀寫就不成立了,而這正是流存儲必須堅持的,這和HBase不一樣。那麼在此原則下,隨着時間的流式,存在Data Skew是必然的,因此,Rebalance也是必然的。流存儲本身最初也不可能預知每個Topic將如何增長數據,當然加上預測能力自動Rebalance是個好主意。

不僅數據會Skew,內存的使用也可能有Skew的情況,這也是節點宕機、或出現其它問題的原因之一,同樣需要在不影響讀寫的情況下自動Rebalance,而且不影響副本數量。

監控與告警

這是所有系統必須做到的,流存儲作爲Dataflow模型計算體系的必要組成部分,是數據的大Buffer、大Hub,它有了問題,影響可想而知。包括CPU、Disk、Memory、Network、Producer、Consumer等都要監控,一旦發生情況,就應當直接通過告警機制連通On-call Shift及時處置或者Auto Heal。不論採用什麼樣的流存儲技術,都嚴重依賴內存大小、磁盤吞吐率、網絡延遲、文件系統調優,因爲流存儲的重點就在於分佈式環境下流式的高速讀寫,所以必須把這些方面的監控做好。

磁盤用量的管控

要綜合根據所有的Retention(Time/Size Based)、複製的情況對總體磁盤用量有個預判,現有的磁盤容量在將來是否夠用,要在使用的過程中動態判斷,所以輔助一些ML手段去預測還是非常好的。如果用Kafka,在計算中,要記得它是以Segment爲單位進行刪除,在Retention到限以後。

監控****消費滯後

如果消費速度小於生產者的寫入速度,意味着終端用戶看到的是不新鮮的數據、不及時的數據,即:新鮮度不好、不及時。其實監控讀、寫滯後,都有意義,讀Lag指讀的Offset所對應的時間點與當時寫的Offset對應的時間點之間的時間差,寫滯後指與上一次寫動作之間的時間差,它們反應的問題是不同的。也許技術上沒問題,但是業務上一定會對數據的新鮮度有要求。

4.2 技術推薦

當前,大家首選Kafka的可能性比較大,它憑藉對Pagecache的順序讀寫和Zero-Copy完成高速讀寫,這非常棒,從模型角度看高速讀寫也應當是以Dataflow模型爲核心的批流統一架構體系中的流存儲所必須的能力。這裏就不贅述它優秀特徵,只對大家在實踐中可能遇到的問題做個提示:

  • Topic達到幾千個可能就會有問題,主要是由於file handler的限制;
  • 租戶隔離,當一個節點上的一個分區在一個消費者或一個生產者出現滯後的現象,那這個節點上所有其它分區上的動作都會滯後;
  • 缺乏針對多租戶的計費計量能力,在生產者和消費者上;
  • 隊列能力支持不夠,如:Delay Queue;
  • 監控方面做得不大好,沒有完整的監控工具;
  • 有時寫生產者和消費者時,可能希望同時使用多個Topic,如果對Topic有通配符能力可能更靈活;
  • API是由不同的個人和公司維護的,與整體發展不同步;
  • Likedin使用Kafka非常重,達到7 Trillion Per Day,4000 Brokers。爲此,Linkedin內部做了補丁分支(不是Fork),爲了滿足增減Broker的運維工作和特有的特徵,已開放到Github。Scalability方面的主要問題是,內存造成的Controller Failure和Slow,解決的方法是重用UpdateMetadataRequest。還有一個問題是啓動或關閉一個Broker(一次只能操作一個)比較慢,改進方法是減少鎖競爭。由於運維的需要,增減Broker會很頻繁,Linkedin給Broker增加了維護模式,以免有消息不斷流入,這樣才能安全地移除,最終保障副本的數量。
  • 沃爾瑪也碰到了恢復失敗節點而造成不好的影響,缺乏再分區的能力,如何跟蹤Rebalance的進度,並確保期間生產與消費都正常還是滿重要的;
  • 缺乏Cloud/Rack/Azure Awareness;

Kafka是大部分人首先想到的,畢竟早5年起家,在社區的豐富性和規模上都有優勢。而作爲後起之秀的Pulsar的社區在Slack上很活躍、在壯大、響應快,這裏把Apache Pulsar的特點介紹一下,在生產實踐中可能不失爲一個可以考慮的選項(當然,任何技術在生產實踐中都可能碰到問題):

  • 經歷過每天處理上千億的數據、上百萬的Topic的生產考驗,Battle-Tested;
  • 流與隊列的合體,單一的API,而Kafka側重流;
  • 可以通過Producer或者Broker直接去重;
  • 分區不是必須的,不必像Kafka一樣要考慮分區與Consumer的數量。它在Topic與Consumer之間加入了Subscription(Exclusive/Failover/Shared/Key_shared)抽象,甚至於一個Subscription可以對應多個Topic。分區時吞吐量可以非常大。
  • 資料表明,Kafka加一個Broker,再平衡分區會比較慢,而Pulsar把Segments分佈式地用Bookeeper存儲緩解了這個問題。這道理是講得通的,因爲在kafka中數據的存儲邏輯細分下來依次是這樣的一對多的關係:Topic/Broker/Partition/Segement/三個文件,因此,在Kafka中一個Partition的所有Segement都在一個Broker上,而在Pulsar中是分散到Bookeeper;Pulsar的負載均衡是自動的,它檢測完全無狀態的Broker的Cpu/Mem/Network IO,自動執行Rebalance;
  • 支持Geo-replication,即:跨機房複製;
  • 阿里、滴滴等大公司支持的行業分析公司的基準測試表明,Pulsar比Kafka在吞吐量和延遲方面都有顯著的優勢;
  • 支持多租戶,每個租戶可以有多個Namespace,在加上Quota、訪問控制、Rate-limit,可以實現豐富的權限管理。通過Namespace可以實現集羣之間的複製;
  • 以Quorum的方式副本複製,性能表現更爲穩定;
  • 分層存儲,Tiered Storage,允許把老的積壓數據卸載到長期的、經濟的存儲中,如:HDFS。例如:用戶行爲數據需要長期保存,以便機器學習訓練用於訓練模型;
  • 生產者到消費者的消息加密,保障絕對的安全,Pulsar自己不保管Key;
  • 一個集羣可以服務上百萬的Topic,但是Kafka達到幾千個就出狀況了;
  • 現成的CDC Connector for MySQL/PostgreSQL,還有好多內置的Source/Sink Connector;
  • 支持消息的TTL;

5 流計算及結果的應用

5.1 主流技術參考與架構

5.2 Flink及其生產實踐

目前的流計算實現,Flink幾乎是不二之選,好多公司在做從Sorm和Spark到Flink的遷移,而且它符合Dataflow模型,很多大企業都有成功的運用,社區發展得如火如荼,改進也很迅速。雖然說Beam出自Google本家,但它的定位不一樣,可以認爲它是Spark/Flink/Samza等流計算引擎之上的一層東西,它爲定義和執行數據處理流程提供了不同語言的SDK,爲不同的引擎提供了不同的Runner。這裏不介紹Flink特徵,官網最好了,僅對生產實踐可能有幫助的內容做一些分享:

  • Latency與Guaranteed Delivery之間的權衡,對於Mission-Critical的作業,保存狀態很重要,以備某種狀況下的接續恢復執行、甚至倒帶。然而,對於一個算子,如果採用Exactly Once,只要它的算子存在多進或者多出的情況,就要做Barrier Alignment,即:要等待第n個Checkpoint的數據都到達,否則不會處理已經到達的第n+1個Checkpoint的數據,這當然就增加Latency;如果採用At Least Once,則不發生Barrier Alignment。所以要根據具體業務情況決策,另一個途徑是降低Parallelism,如果可以的話。
  • 存儲狀態造成的Latency,三種State Backend默認都是以異步方式保存狀態而不阻塞流的處理,但是Heap+RocksDB的組合方式是不支持Timer State的;
  • 資源隔離,Yarn+Cgroup隔離CPU和Memory;用Yarn Node Label實現機器、容器顆粒度的資源保障優先級和專用保障;
  • 使用Asynchronous I/O 調用dubbo接口,Zuul、DB、HBase等外部接口;
  • Blink Planner有更好的性能表現;
  • App1(由多個作業構成)和App2可以共享中間結果,結果共享可以很大程度上節約資源;
  • 如果對一個流要做事件處理,但是可能有好多規則、不僅規則本身會變化、而且規則也會增減,配置驅動是最好的方式;
  • 宜早不宜遲
    • Java對象的空間代價差不多是翻倍的,相對於Primitive Type而言。Flink在網絡計算、Checkpioint的時候是要涉及Serde(序列化、反序列化)的,所以在Serde上發力肯定會在內存優化、速度上大有收益的,例如:自己造一個時空高效的、完全基於Primitive 的數據結構,也是完全可行的;在什麼階段實施這個要看情況了,因爲個性的Serde可能意味着與周邊的第三方系統不兼容,但時空收益那是肯定的;
    • Ingestion階段,可以把一個消息按不同的分區方式(即:用不同的Key值打散)產生多個流輸入流存儲中,這樣可以以空間換時間,因爲它可以讓流計算階段省卻網絡Shuffle。
    • Ingestion階段,第一時間維護維表,Redis/HBase/es/Aerospike,如果採用外在存儲方式保存維表的話;
    • Ingestion階段,第一時間把ID變成數值型,可以用bitmap,在有些問題上很有用;
    • Pushdown,不論是使用API還是SQL,都要儘可能把聚合、過濾等計算先在小數據集上完成、然後再Join,而不是在Join後的更大的數據集上進行。能在一個Task中先做到的就在一個Task裏先做盡、能在一個Taskmanager中先做到的就在一個Taskmanager裏先做盡、能在一個Table中先做到的就在一個Table裏先做盡、最後纔是Join等需要網絡Shuffle的動作,這是高效計算的次第;
    • Ingestion階段,分而治之,在使用上完全不相干的數據就不應當發到同一個topic;
  • 數據倉庫
    • 實時數倉中,需要用到維表,方法估計至少5種,其中以Temporal Table Function方式最佳,數據量大、實時性強;
    • 離線數倉,數據表明基於Flink的效率至少比HiveOnTez要高;
  • 流存儲的分區數是Flink Parallelism的整數倍爲好,以防數據Skew;
  • 常見問題
    • 數據Skew、頻繁GC、對周邊慢讀慢些、大窗口、Serde(Shuffle and State Backend);
    • 注意設置State TTL,以免長時間跨度的計算需要數據的時候數據已經被clean了;
    • 監控不足,作業級、算子級、Backpressure、Executionstate、Jobstatus、ZK、上下游;
  • 作業發佈
    • 檢查與在運行的老版本的state的兼容性問題,回滾能力,選擇Sheckpoint、批量升級、審批流程;動態修改作業的執行邏輯是有風險的,如:SQL、代碼,可能需要增強State的維護邏輯(如:狀態比對)、甚至使用其它存儲;State Processor API挺有用的,可以讀寫分析State,所以對State維護很有幫助;
    • 作業可以是基於API寫的,但是更推薦可配置SQL的方式、並結合版本控制。一種是把SQL翻譯成DataSet API或者DataStream API;一種是把自定義的某種聲明式的配置翻譯成API的執行;還可以通過把SQL提交給AthenaX來提交作業;要麼做自己的SQL執行機制,Query Parser/Optimizer/Planner,然後改造運行時,跳過2個API,不過這就要改Flink了;
    • 還有一種情況是,在不重新啓動作業的情況下,動態更新SQL及其它配置也是可行的,結合ZK的Watch Push機制;
    • 總之,SQL具有可維護性好、接受度高、維護成本低、可動態修改、規範、可配置等優點,一直是不錯的User API,儘可能與具體實現技術解耦、保持Portability,是個不錯的方向,也更容易爲沒有專業技術背景的Citizen Developer服務,而不是讓終端用戶學習各種技術;
  • 如果想在流上應用ML模型,先把計算結果流入流存儲(如:Kafka),然後加一層消費者作爲模型應用層更爲合適,由其是在應用多個模型在同一個流上的情況,這樣可以把特徵準備與模型運用解耦,互相不干擾、獨立Scale,而不和流計算混合在同一個進程中;
  • 複雜事件的處理
    • CEP,SQL的match_recognize(ISO標準SQL的一部分)或者DataStream上的API,它的強大在於通過Pattern來識別是否一個事件發生了,例如:統計沒有點擊的廣告展現(涉及展現和點擊兩個事件,但是在規定時間內點擊事件沒有到達),就可以用這個。Flink-siddhi是個值得參考的實現;
    • Stateful Function framework,融合了Flink與FaaS(例如:AWS Lambda 和微軟的Virtual Stateful Actor Model),這是個複雜的框架,如果描述概念恐怕不好理解,這裏舉個例子:假設任務是這樣的,從Kafka輸入的消息爲Tuple(user_id=111,“張三”),作爲結果向Kafka輸出的消息爲Tuple(user_id=111,“歡迎張三的第N次訪問”),這裏顯然要維護每個人的訪問次數,該框架的做法是,當一個Taskmanager收到一個用戶的消息的時候,可以把這個消息按用戶路由到維護着該用戶狀態(訪問次數)的函數去處理,而這個函數可能位於當前的Taskmanager、也可能位於集羣的另一個Taskmanager,就是這樣的。再擴展一下,在網約車的場景裏,司機與乘客發生兩個消息流進入系統,通過司機、乘客、Geo Index、Ride等有狀態函數之間的交互最後完成乘客的Book和司機的Bid。這個很像電信領域的霸主Erlang的Actor Model,其實Flink本身的協調也用到了Actor Model(即:Akka)。總結,這個框架一方面可以用於複雜事件的處理(狀態機),另一方面也可以用於極低延遲要求的動態AI模型的運用(每一個待預測個體都有自己的狀態),不過像金融領域的情況可能還是比較挑戰,因爲特徵計算本身可能就需要高強度計算,涉及4、5千個變量不稀奇。
  • 基本方針
    • 作爲用戶的開發者的自由度越小越好,從總體的規範度、代碼質量、系統穩定性、可維護性、可控性、綜合成本等方面考慮,通過提供Scaffold、Framework、SDK、Platform、Configuration、Code Checker、UDF、SQL等方式滲透到軟件研發的全生命週期是非常可取的,當然這與開發者的探索慾望是矛盾的,但從企業的角度是非常值得的。
    • 要儘可減少網絡Shuffle次數和IO的量、高效利用內存、索引、增量計算、少做無用功、複用累積成果、高效的Serde;

5.3 支持SQL的技術

大家非常希望數據具有較高的新鮮度,即:在企業範圍內從數據產生的那一刻直到被最終真正用起來的那一刻之間的時間越短越好。基於這樣的期望,自然想到直接對接Kafka的DB,然後用SQL直接得到結果,畢竟SQL有很多優勢,以下介紹幾種選項:

  • Rockset,它是由一羣原來在Facebook做搜索的、在Google做Gmail的、在Oracle做數據庫的人在一起做出來的,支持各種數據源,尤其是Amazon雲上的,包括Kafka,它支持Full ANSI SQL,通過JDBC或REST在其上可以直接用Graphana/Tableau/RStudio/Superset/Jupyter/Redash/DataGrip,TB級的數據量、毫秒級的Latency,可見其強大,不過它不開源。
  • Presto-Pinot-Connector,Presto擅長ANSI SQL Query,而Pinot擅長OLAP,其實Pinot和Rockset在本質的精華上是一樣的,就是對所有的字段做倒排索引,Pinot也可以直接接Kafka,這個東西也不開源,是Uber做的。Pinot本身是開源的,有很強的的OLAP能力,2019年社區強烈建議增加對SQL的支持,如果有資源也許可以嘗試利用Calcite做自己的Parser/Validation/Optimization/Plan然後對接Pinot。
  • SQL-on-Kafka-with-Presto,一個Presto接多個Kafka集羣,一個Kafka支持多個Topic(Table),這樣就可以通過Presto對Kafka 使用SQL了,可以試試,沒找到性能有關資料。不過應該都沒有Rockset和presto-pinot快。
  • Couchbase,雖然不是完全支持ANSI SQL,但它有自己的查詢語言N1QL(SQL for JSON),N1QL兼顧了大家對SQL的熟悉與JSON的數據結構,其結構、語法都非常像SQL,雖然它沒有Join,但是支持子查詢,支持SDK和REST兩種方式來提交SQL,還支持函數、窗口等好多特徵,這些特點遠勝於搜索引擎,但是索引要主動建立,這個不如搜索引擎。就SQL的支持程度而言,還可以考慮Druid,之所以和Couchbase放在一起,是因爲它也支持子查詢,它叫Semi-join,雖然不支持Join,但是Druid的優勢在於它像搜索引擎一樣不用有意識地建索引。
  • ksqlDB,它的作者是Kafka的Co-creator,ksqlDB通過REST支持SQL,支持負載均衡和自動故障轉移,支持Join。
  • Clickhouse對SQL也有相當不錯的支持。
  • 還有一個辦法是把數據持續流入Elasticsearch或者Solr,不過這兩個的Join能力都較弱,如果不需要Join那還是不錯的。

5.4 一個優秀的K/V存儲

Aerospike雖然不支持Full SQL,但是真的是非常值得考慮的HBase 的替換選項,尤其在要求更高速度的時候。Flink中可以通過TableFunction實現對Aerospike的讀寫,Aerospike的優勢包括:

  • 採用C語言開發;
  • 讀寫明顯比HBase快,K/V查找速度比Redis快20-30%、比Mongo快50%、比Cassandra快45%,非常適合實時性高的應用;
  • Flash-optimized In-memory NoSQL(Key/Value),針對SSD做了專門的優化;
  • 支持二級索引;
  • 支持UDF;
  • 本地集羣的Immediate Consistency和跨數據中心的Eventual Consistency;
  • 支持原子操作;
  • 支持基於用戶與角色的訪問控制;
  • 支持ACID操作;
  • Auto-sharding & Auto-healing,擴容無需手工干預;
  • 可以部署到Kubernetes;
  • 開源,在Reliability、Latency、Scalability上都非常優異,廣泛用在各個行業的關鍵業務的實時場景,如:金融、電訊、廣告、遊戲;
  • HA簡單;
  • 用了非常複雜的哈希算法來避免Data Skew;
  • 支持多種語言;
  • 支持Geo Index;
  • 和RDBMS相對應,其數據模型(括號中是關係型數據庫的概念)是Database/Namespace(Tablespace)/Set(Table)/Record(Row)/Bin(Column),但它是Schemaless。Record上可以有TTL,Generation相當於HBase的Version。一個Namespace最多可以有32k不同的Bin。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章