從MapReduce的興起,就帶來一種思路,就是希望通過大量廉價的機器來處理以前需要耗費昂貴資源的海量數(shù)據(jù)。這種方式事實上是一種架構(gòu)的水平伸縮模式——真正的以量取勝。畢竟,以現(xiàn)在的硬件發(fā)展來看,CPU的核數(shù)、內(nèi)存的容量以及海量存儲硬盤,都慢慢變得低廉而高效。然而,對于商業(yè)應(yīng)用的海量數(shù)據(jù)挖掘或分析來看,硬件成本依舊是開發(fā)商非常關(guān)注的。當(dāng)然最好的結(jié)果是:既要馬兒跑得快,還要馬兒少吃草。 Spark相對于Hadoop的MapReduce而言,確乎要跑得迅捷許多。然而,Spark這種In-Memory的計算模式,是否在硬件資源尤其是內(nèi)存資源的消耗上,要求更高呢?我既找不到這么多機器,也無法租用多臺虛擬instance,再沒法測評的情況下,只要尋求Spark的官方網(wǎng)站,又或者通過Google搜索。從Spark官方網(wǎng)站,Databricks公司Patrick Wendell的演講以及Matei Zaharia的Spark論文,找到了一些關(guān)于Spark硬件配置的支撐數(shù)據(jù)。 Spark與存儲系統(tǒng)如果Spark使用HDFS作為存儲系統(tǒng),則可以有效地運用Spark的standalone mode cluster,讓Spark與HDFS部署在同一臺機器上。這種模式的部署非常簡單,且讀取文件的性能更高。當(dāng)然,Spark對內(nèi)存的使用是有要求的,需要合理分配它與HDFS的資源。因此,需要配置Spark和HDFS的環(huán)境變量,為各自的任務(wù)分配內(nèi)存和CPU資源,避免相互之間的資源爭用。 若HDFS的機器足夠好,這種部署可以優(yōu)先考慮。若數(shù)據(jù)處理的執(zhí)行效率要求非常高,那么還是需要采用分離的部署模式,例如部署在Hadoop YARN集群上。 Spark對磁盤的要求Spark是in memory的迭代式運算平臺,因此它對磁盤的要求不高。Spark官方推薦為每個節(jié)點配置4-8塊磁盤,且并不需要配置為RAID(即將磁盤作為單獨的mount point)。然后,通過配置spark.local.dir來指定磁盤列表。 Spark對內(nèi)存的要求Spark雖然是in memory的運算平臺,但從官方資料看,似乎本身對內(nèi)存的要求并不是特別苛刻。官方網(wǎng)站只是要求內(nèi)存在8GB之上即可(Impala要求機器配置在128GB)。當(dāng)然,真正要高效處理,仍然是內(nèi)存越大越好。若內(nèi)存超過200GB,則需要當(dāng)心,因為JVM對超過200GB的內(nèi)存管理存在問題,需要特別的配置。 內(nèi)存容量足夠大,還得真正分給了Spark才行。Spark建議需要提供至少75%的內(nèi)存空間分配給Spark,至于其余的內(nèi)存空間,則分配給操作系統(tǒng)與buffer cache。這就需要部署Spark的機器足夠干凈。 考慮內(nèi)存消耗問題,倘若我們要處理的數(shù)據(jù)僅僅是進行一次處理,用完即丟棄,就應(yīng)該避免使用cache或persist,從而降低對內(nèi)存的損耗。若確實需要將數(shù)據(jù)加載到內(nèi)存中,而內(nèi)存又不足以加載,則可以設(shè)置Storage Level。0.9版本的Spark提供了三種Storage Level:MEMORY_ONLY(這是默認值),MEMORY_AND_DISK,以及DISK_ONLY。 關(guān)于數(shù)據(jù)的持久化,Spark默認是持久化到內(nèi)存中。但它也提供了三種持久化RDD的存儲方式:
第一種存儲方式性能最優(yōu),第二種方式則對RDD的展現(xiàn)方式(Representing)提供了擴展,第三種方式則用于內(nèi)存不足時。 然而,在最新版(V1.0.2)的Spark中,提供了更多的Storage Level選擇。一個值得注意的選項是OFF_HEAP,它能夠?qū)DD以序列化格式存儲到Tachyon中。相比MEMORY_ONLY_SER,這一選項能夠減少執(zhí)行垃圾回收,使Spark的執(zhí)行器(executor)更小,并能共享內(nèi)存池。Tachyon是一個基于內(nèi)存的分布式文件系統(tǒng),性能遠超HDFS。Tachyon與Spark同源同宗,都烙有伯克利AMPLab的印記。目前,Tachyon的版本為0.5.0,還處于實驗階段。 注意,RDDs是Lazy的,在執(zhí)行Transformation操作如map、filter時,并不會提交Job,只有在執(zhí)行Action操作如count、first時,才會執(zhí)行Job,此時才會進行數(shù)據(jù)的加載。當(dāng)然,對于一些shuffle操作,例如reduceByKey,雖然僅是Transformation操作,但它在執(zhí)行時會將一些中間數(shù)據(jù)進行持久化,而無需顯式調(diào)用persist()函數(shù)。這是為了應(yīng)對當(dāng)節(jié)點出現(xiàn)故障時,能夠避免針對大量數(shù)據(jù)進行重計算。要計算Spark加載的Dataset大小,可以通過Spark提供的Web UI Monitoring工具來幫助分析與判斷。 Spark的RDD是具有分區(qū)(partition)的,Spark并非是將整個RDD一次性加載到內(nèi)存中。Spark針對partition提供了eviction policy,這一Policy采用了LRU(Least Recently Used)機制。當(dāng)一個新的RDD分區(qū)需要計算時,如果沒有合適的空間存儲,就會根據(jù)LRU策略,將最少訪問的RDD分區(qū)彈出,除非這個新分區(qū)與最少訪問的分區(qū)屬于同一個RDD。這也在一定程度上緩和了對內(nèi)存的消耗。 Spark對內(nèi)存的消耗主要分為三部分:
一個通常的內(nèi)存消耗計算方法是:內(nèi)存消耗大小= 對象字段中原生數(shù)據(jù) * (2~5)。 這是因為Spark運行在JVM之上,操作的Java對象都有定義的“object header”,而數(shù)據(jù)結(jié)構(gòu)(如Map,LinkedList)對象自身也需要占用內(nèi)存空間。此外,對于存儲在數(shù)據(jù)結(jié)構(gòu)中的基本類型,還需要裝箱(Boxing)。Spark也提供了一些內(nèi)存調(diào)優(yōu)機制,例如執(zhí)行對象的序列化,可以釋放一部分內(nèi)存空間。還可以通過為JVM設(shè)置flag來標(biāo)記存放的字節(jié)數(shù)(選擇4個字節(jié)而非8個字節(jié))。在JDK 7下,還可以做更多優(yōu)化,例如對字符編碼的設(shè)置。這些配置都可以在spark-env.sh中設(shè)置。 Spark對網(wǎng)絡(luò)的要求Spark屬于網(wǎng)絡(luò)綁定型系統(tǒng),因而建議使用10G及以上的網(wǎng)絡(luò)帶寬。 Spark對CPU的要求Spark可以支持一臺機器擴展至數(shù)十個CPU core,它實現(xiàn)的是線程之間最小共享。若內(nèi)存足夠大,則制約運算性能的就是網(wǎng)絡(luò)帶寬與CPU數(shù)。 Spark官方利用Amazon EC2的環(huán)境對Spark進行了基準(zhǔn)測評。例如,在交互方式下進行數(shù)據(jù)挖掘(Interative Data Mining),租用Amazon EC2的100個實例,配置為8核、68GB的內(nèi)存。對1TB的維基百科頁面查閱日志(維基百科兩年的數(shù)據(jù))進行數(shù)據(jù)挖掘。在查詢時,針對整個輸入數(shù)據(jù)進行全掃描,只需要耗費5-7秒的時間。如下圖所示: 在Matei Zaharia的Spark論文中還給出了一些使用Spark的真實案例。視頻處理公司Conviva,使用Spark將數(shù)據(jù)子集加載到RDD中。報道說明,對于200GB壓縮過的數(shù)據(jù)進行查詢和聚合操作,并運行在兩臺Spark機器上,占用內(nèi)存為96GB,執(zhí)行完全部操作需要耗費30分鐘左右的時間。同比情況下,Hadoop需要耗費20小時。注意:之所以200GB的壓縮數(shù)據(jù)只占用96GB內(nèi)存,是因為RDD的處理方式,使得我們可以只加載匹配客戶過濾的行和列,而非所有壓縮數(shù)據(jù)。 高危漏洞頻發(fā),隱私泄露,普通開發(fā)者該如何避免和防范;開發(fā)者如何從邏輯上避免風(fēng)險?在【QCon北京2015】“新時代的安全”專題中,在Pwn2Own 2015上奪冠的Keen Team安全研究員Peter Hlavaty將解讀內(nèi)核安全精髓;阿里巴巴安全專家祝建躍將分享互聯(lián)網(wǎng)全球最大DDoS攻擊防御實戰(zhàn)。
|
|