在大规模系统中使用Scala
本文是關(guān)于在大規(guī)模數(shù)據(jù)儲存及分析系統(tǒng)中使用Sacla系列文章中的第一篇。
\\在過去幾年間,已經(jīng)有多個項目使用了Scala進行大規(guī)模數(shù)據(jù)儲存及分析平臺的設(shè)計。
\\BBC在設(shè)計公司內(nèi)部的RDF數(shù)據(jù)儲存系統(tǒng)時就使用了Scala以及Scalatra HTTP框架,這套內(nèi)部系統(tǒng)可用于查詢BBC新聞與體育所有文章中的鏈接數(shù)據(jù)。
\\在整個2014年間,業(yè)界對于Apache Spark的興趣達到了一個高峰,這是一套使用Scala編寫的數(shù)據(jù)分析工具。Spark中包含了一套由Spray編寫的HTTP接口,它的后端使用了Akka用于并行處理。
\\邁凱倫應(yīng)用技術(shù)(MAT)在他們的數(shù)據(jù)分析平臺中也使用了Scala、Scalatra和Akka,作為整個平臺的構(gòu)建基礎(chǔ)。
\\為什么這些項目會選擇Scala呢?
\\為了找到這一問題背后的原因,我們與來自MAT的高級軟件工程師Andrew Jayne進行了一次對話,了解了后者使用Scala創(chuàng)建一個自定義的高性能數(shù)據(jù)儲存系統(tǒng)的經(jīng)驗。
\\邁凱倫應(yīng)用技術(shù)位于倫敦附近,它源自于母公司邁凱倫幾十年以來在F1賽車方面的經(jīng)驗。從母公司分離之后,MAT也將F1的相關(guān)經(jīng)驗應(yīng)用在其它產(chǎn)業(yè)上。
\\由于MAT深厚的F1背景,因此它們在根據(jù)數(shù)據(jù)進行分析以及進行快速決策方面具備很強的技術(shù)實力,例如它們的時間序列數(shù)據(jù)存儲系統(tǒng)能夠分析一場F1賽事中車輛的數(shù)據(jù)流。不過,他們也發(fā)現(xiàn)這套序列分析技術(shù)在與傳感器設(shè)備相結(jié)合的情況下,往往能夠應(yīng)用在賽車之外的其它許多場景中:他們已經(jīng)對制造業(yè)、傳輸業(yè)、能源業(yè)以及醫(yī)療保健行業(yè)的部門提出了這項建議。
\\為了支持MAT的這項咨詢工作,他們的工程師創(chuàng)建了一個序列數(shù)據(jù)平臺,運行于AWS之上。
\\InfoQ:你是否能為我們概述一下MAT序列數(shù)據(jù)儲存系統(tǒng)的作用是什么,以及如何使用它?
\\\Jayne:這是一個大容量、高性能的排序式鍵-值存儲系統(tǒng),它能夠保存讀-寫的一致性,并且具有一個專門為實時及歷史序列數(shù)據(jù)(根據(jù)時間、距離、深度等進行索引)設(shè)計的特性集。它允許我們以一種版本控制的方式進行微批量及批量處理,并且可以通過某個REST API對我們的數(shù)據(jù)分析平臺的輸入與輸出的所有序列進行持久化。這方面有一個例子,我們正在為葛蘭素史克(GSK)設(shè)計對漸凍癥(ALS)患者進行監(jiān)控與分析的系統(tǒng),這是基于傳感器設(shè)備的,通過臨床實驗,讓我們能夠得到在實驗中患者的病癥得到改善,或產(chǎn)生惡化的反饋信息。
\\\InfoQ: MAT序列數(shù)據(jù)存儲系統(tǒng)是否是用于分析F1相關(guān)的時間序列數(shù)據(jù)的目的,還是更為一般性的目的而存在的?
\\\Jayne:設(shè)計這套系統(tǒng)的目的是作為一種一般性的解決方案,對序列數(shù)據(jù)進行保存與查詢,它基于我們在賽車運動、競技體育、醫(yī)療以及能源行業(yè)的經(jīng)驗。我們在這些項目中都面臨著類似的問題,因此急需一種存儲方案,它能夠保持數(shù)據(jù)完整性,同時又能幫助我們解決這些問題。比方說,如果你的數(shù)據(jù)來自于某個產(chǎn)生了時鐘漂移的設(shè)備,你該怎么做?如果出于帶寬的限制,使得上傳的數(shù)據(jù)只具有較低的分辨率,那么我們又該如何確保數(shù)據(jù)的高精度?如果在一段長時間的網(wǎng)絡(luò)斷線之后,某個數(shù)據(jù)源又開始發(fā)送數(shù)據(jù),那么又會發(fā)生什么情況?
\\\InfoQ:這套系統(tǒng)主要針對怎樣的數(shù)據(jù)集,目標(biāo)的數(shù)據(jù)量是什么?
\\\Jayne:它可以用于n維的數(shù)值數(shù)據(jù),其中包含一個數(shù)值型的、嚴格增長的鍵。目前我們的用例除了我們的數(shù)據(jù)分析結(jié)果之外,還包含病患監(jiān)控設(shè)備的傳感器數(shù)據(jù)、鉆井作業(yè)以及數(shù)據(jù)中心。
\\\InfoQ:為什么選擇Scala?你的技術(shù)背景是從Java轉(zhuǎn)移而來的嗎?這門語言有什么地方吸引了你?
\\\Jayne:整個團隊具有多種語言的背景。在2012之前,我們使用了Java、C#和MATLAB。隨著Typesafe Stack 2.0發(fā)布之后,我們就開始采用Scala作為我們的服務(wù)以及web應(yīng)用程序的后端語言。
\\當(dāng)時Scala最吸引我們的地方在于它的可伸縮性,例如可以通過使用Actor、不可變對象以及函數(shù)式編程簡化并發(fā)處理。此外還有一些原因,比如能夠以更加算術(shù)式的語法表達程序、模式匹配,并且能夠減少樣板代碼。不過,如果要犧牲Java的互操作性,那我們也不可能會選擇Scala。函數(shù)式編程的方式非常新穎、痛快,也為我們展現(xiàn)了更多創(chuàng)新的機會。這個選項很符合團隊的文化與心態(tài)。
\\\InfoQ:為什么這套系統(tǒng)沒有選擇Java?
\\\Jayne:我們已經(jīng)有了一個用Java編寫并基于Hadoop的組件。雖然我們也可以在這個組件的基礎(chǔ)上打造新系統(tǒng),但其它所有后臺組件都是用Scala編寫的。我們將此看做一次開展研究工作的好機會,很快我們就明白,要支持我們所設(shè)計的架構(gòu),可以選擇的類庫與技術(shù)有哪些了。基于這些研究的經(jīng)驗,我們意識到可以用函數(shù)式編程簡化我們的現(xiàn)有功能。雖然Java很易于使用,但它的語法過于啰嗦,會妨礙我們保持代碼清晰度的意圖。我們已經(jīng)在商業(yè)項目中使用Scala有很多年了,我們發(fā)現(xiàn)能夠與創(chuàng)建這門語言以及核心類庫的人們進行交流是很有價值的。
\\\InfoQ:其它的一些時間序列數(shù)據(jù)庫(TSDB)缺少了什么功能?為什么沒有選擇KairosDb、Druid、InfluxDb、OpenTSDB,或其它任何一種現(xiàn)有的TSDB?
\\\Jayne:對于我們的業(yè)務(wù)來說,數(shù)據(jù)完整性與數(shù)據(jù)管理是至關(guān)重要的,并且我們需要對這些數(shù)據(jù)進行某些程度的保證,以符合代碼端的期望。僅僅實現(xiàn)備份與記錄日志是不夠的。受到了Git的影響,我們最終設(shè)計了一套數(shù)據(jù)儲存系統(tǒng),它具有基于提交的版本控制能力,以及基于樹狀的組織結(jié)構(gòu)。
\\我們的驗收場景也提出了額外的挑戰(zhàn),例如:
\\- 原子性 —— 不允許在查詢系統(tǒng)時返回不一致的狀態(tài)。\\
- 一致性與正確性 —— 查詢應(yīng)當(dāng)是可重復(fù)的,并且始終返回一致的、正確的數(shù)據(jù)。\\
- 接近實時的寫操作 —— 支持每秒幾百萬次寫入操作(數(shù)據(jù)來自于高頻率及可變頻率的傳感器),并且在數(shù)據(jù)寫入后的幾秒鐘之內(nèi)就可用于查詢。\\
- 查詢性能 —— 通過在整個頻道中提供可預(yù)測且快速的查詢,支持能夠感知延遲的數(shù)據(jù)分析能力,包括: \
- 數(shù)據(jù)準備(即插值),\\
- 子集(即窗口、范圍、偏移、限制),\\
- 聚合(即平均值、最小值、最大值等等),\\
- 預(yù)測(即推斷、回歸、關(guān)聯(lián))\
- 語言無關(guān)性 —— 使用REST API與ETag緩存。\\
- 通用的數(shù)據(jù)格式 —— 數(shù)據(jù)應(yīng)當(dāng)與現(xiàn)有的工具兼容,例如CSV、JSON等等。\\
- 部署復(fù)雜性 —— 系統(tǒng)應(yīng)當(dāng)使用現(xiàn)有的云端基礎(chǔ)設(shè)施(AWS),并且能夠以最小的代價創(chuàng)建新的數(shù)據(jù)存儲。\
這些需求中有很大一部分已經(jīng)在現(xiàn)有的TSDB中已經(jīng)得到解決,其中某些TSDB對這些問題的解決方案更為出色。但是,我們所需的某些查詢是其它數(shù)據(jù)庫所不支持的,也很難對其進行改進。主流的TSDB都是在其它數(shù)據(jù)庫系統(tǒng)的基礎(chǔ)上創(chuàng)建的(例如HBase),它們的復(fù)雜性已經(jīng)超出了我們的用例的需求。通過使用一種更簡化的、量身訂做的存儲機制,并利用分布式特性,我們就能夠?qū)?shù)據(jù)的組織進行優(yōu)化,更適用于我們所執(zhí)行的查詢。這種方式也讓系統(tǒng)管理員的工作量以及運行時的成本減至最小。最重要的是,其它數(shù)據(jù)庫都無法提供這種對數(shù)據(jù)的版本控制機制,而我們在開發(fā)與生產(chǎn)環(huán)境中都需要這種機制。
\\\InfoQ:說到REST API,你在項目中使用了Scalatra作為REST HTTP接口,原因是什么?
\\\Jayne:Scalatra的維護工作做得很好,它的發(fā)布策略也很明智,我們之前在使用其它框架時曾在這一點上吃過虧。這個框架有一套十分簡單的領(lǐng)域特定語言(DSL),我們只需要進行很少的工作,即請求處理與測試。并且它還能夠使用我們選擇的其它類庫,進行諸如序列化等工作。Scalatra能夠簡單地部署到某個servlet容器中是它的一大優(yōu)點,并且它的性能也十分出色。
\\\InfoQ:你提到了Actor。那么Akka這個選擇在實際運行中效果如何?我聽說某些人對它愛不釋手,而另一些人則表示自從他們遠離了Akka之后,代碼就變得簡單了許多倍。那么使用它的挑戰(zhàn)又來自于哪里呢?
\\\Jayne:我們在數(shù)據(jù)儲存系統(tǒng)中使用Akka管理異步的請求,因為一個請求的生命周期中的大部分都是進行I/O操作。它目前還不是一種基于事件的I/O技術(shù),但我們認為Akka的優(yōu)點在于它的調(diào)度器以及對棧溢出的處理。
\\我們使用了actor模型將某一問題分解為多個子系統(tǒng)集,每個子系統(tǒng)維護自己的狀態(tài),負責(zé)自己的可伸縮性。由于在設(shè)計時就考慮到了默認的分布式架構(gòu),因此你可以利用它的位置透明性特征實現(xiàn)縱向與橫向的擴展。不過,由于失去了正式的接口,這一點也讓我們產(chǎn)生了動搖,因為這意味著我們將失去編譯器檢查的優(yōu)勢。一種妥協(xié)方案是使用正規(guī)的協(xié)議,讓actor保持簡潔,并讓這些協(xié)議在我們的設(shè)計與測試中明確地表現(xiàn)出來。編寫清晰的、簡明的測試不是一件簡單的事,而在任何并發(fā)系統(tǒng)中進行調(diào)試都是一個很大的挑戰(zhàn)。
\\\InfoQ:這套數(shù)據(jù)庫能夠在多個節(jié)點間進行集群化嗎?它的橫向擴展能力如何?這一點與你們選擇了Scala的決定是否有關(guān),還是說無論使用哪一種語言結(jié)果都一樣呢?
\\\Jayne:目前來說,它僅在數(shù)據(jù)處理量以及故障轉(zhuǎn)移方面做到了可伸縮性,因為API終結(jié)點與數(shù)據(jù)的位置是在一起的。接下來在改善可伸縮性方面的工作是移除這一限制,這樣我們就可以在REST API端使用一種靈活的負載均衡器,并將其從數(shù)據(jù)儲存層中分解出去。
\\使用Scala進行開發(fā)的速度是非常之快的,并且使用函數(shù)式編程能夠讓許多最復(fù)雜的處理過程也變得十分清晰。默認的不可變性也鼓勵更清晰的編程模式,并且更容易實現(xiàn)對系統(tǒng)的原子性與一致性的強制實施。不過,在Java中也沒有什么不能做到的,只是我們覺得Scala是最適合我們團隊的工具。
\\\關(guān)于作者
\\Dave Hrycyszyn是 Head London的技術(shù)總監(jiān),這是一家位于英國的數(shù)字產(chǎn)品與服務(wù)代理商。Dave是 《Scalatra in Action》一書的作者之一,也是創(chuàng)建Scalatra這個微框架的團隊的成員之一。他在自己的博客constructiveproof.com上撰寫了大量有關(guān)于Scala、API和與數(shù)據(jù)相關(guān)的主題文章。
\\查看英文原文:Scala in Large Scale Systems
總結(jié)
以上是生活随笔為你收集整理的在大规模系统中使用Scala的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 模块常用命令
- 下一篇: Swift 新特性 - 访问控制(Acc