Hadoop寨蹋、Spark等5種大數(shù)據(jù)框架對(duì)比

? ? ? ? 大數(shù)據(jù)是收集、整理扔茅、處理大容量數(shù)據(jù)集已旧,并從中獲得見解所需的非傳統(tǒng)戰(zhàn)略和技術(shù)的總稱。雖然處理數(shù)據(jù)所需的計(jì)算能力或存儲(chǔ)容量早已超過一臺(tái)計(jì)算機(jī)的上限召娜,但這種計(jì)算類型的普遍性运褪、規(guī)模,以及價(jià)值在最近幾年才經(jīng)歷了大規(guī)模擴(kuò)展玖瘸。

? ? ? ? ?本文將介紹大數(shù)據(jù)系統(tǒng)一個(gè)最基本的組件:處理框架秸讹。處理框架負(fù)責(zé)對(duì)系統(tǒng)中的數(shù)據(jù)進(jìn)行計(jì)算,例如處理從非易失存儲(chǔ)中讀取的數(shù)據(jù)雅倒,或處理剛剛攝入到系統(tǒng)中的數(shù)據(jù)璃诀。數(shù)據(jù)的計(jì)算則是指從大量單一數(shù)據(jù)點(diǎn)中提取信息和見解的過程。

? ? ? ? 下文將介紹這些框架:

? ? ? ? 僅批處理框架:

? ? ? ? Apache Hadoop

? ? ? ? 僅流處理框架:

? ? ? ? Apache Storm

? ? ? ? Apache Samza

? ? ? ? 混合框架:

? ? ? ? Apache Spark

? ? ? ? Apache Flink

大數(shù)據(jù)處理框架是什么屯断?


? ? ? ? 處理框架和處理引擎負(fù)責(zé)對(duì)數(shù)據(jù)系統(tǒng)中的數(shù)據(jù)進(jìn)行計(jì)算文虏。雖然“引擎”和“框架”之間的區(qū)別沒有什么權(quán)威的定義侣诺,但大部分時(shí)候可以將前者定義為實(shí)際負(fù)責(zé)處理數(shù)據(jù)操作的組件,后者則可定義為承擔(dān)類似作用的一系列組件氧秘。

? ? ? ? 例如Apache Hadoop可以看作一種以MapReduce作為默認(rèn)處理引擎的處理框架年鸳。引擎和框架通常可以相互替換或同時(shí)使用丸相。例如另一個(gè)框架Apache Spark可以納入Hadoop并取代MapReduce搔确。組件之間的這種互操作性是大數(shù)據(jù)系統(tǒng)靈活性如此之高的原因之一。

? ? ? ? 雖然負(fù)責(zé)處理生命周期內(nèi)這一階段數(shù)據(jù)的系統(tǒng)通常都很復(fù)雜灭忠,但從廣義層面來看它們的目標(biāo)是非常一致的:通過對(duì)數(shù)據(jù)執(zhí)行操作提高理解能力膳算,揭示出數(shù)據(jù)蘊(yùn)含的模式,并針對(duì)復(fù)雜互動(dòng)獲得見解弛作。

? ? ? ? 為了簡化這些組件的討論涕蜂,我們會(huì)通過不同處理框架的設(shè)計(jì)意圖,按照所處理的數(shù)據(jù)狀態(tài)對(duì)其進(jìn)行分類映琳。一些系統(tǒng)可以用批處理方式處理數(shù)據(jù)机隙,一些系統(tǒng)可以用流方式處理連續(xù)不斷流入系統(tǒng)的數(shù)據(jù)。此外還有一些系統(tǒng)可以同時(shí)處理這兩類數(shù)據(jù)萨西。

? ? ? ? 在深入介紹不同實(shí)現(xiàn)的指標(biāo)和結(jié)論之前有鹿,首先需要對(duì)不同處理類型的概念進(jìn)行一個(gè)簡單的介紹。

批處理系統(tǒng)


? ? ? ? 批處理在大數(shù)據(jù)世界有著悠久的歷史谎脯。批處理主要操作大容量靜態(tài)數(shù)據(jù)集葱跋,并在計(jì)算過程完成后返回結(jié)果。

? ? ? ? 批處理模式中使用的數(shù)據(jù)集通常符合下列特征...

? ? ? ? 有界:批處理數(shù)據(jù)集代表數(shù)據(jù)的有限集合

? ? ? ? 持久:數(shù)據(jù)通常始終存儲(chǔ)在某種類型的持久存儲(chǔ)位置中

? ? ? ? 大量:批處理操作通常是處理極為海量數(shù)據(jù)集的唯一方法

? ? ? ? 批處理非常適合需要訪問全套記錄才能完成的計(jì)算工作源梭。例如在計(jì)算總數(shù)和平均數(shù)時(shí)娱俺,必須將數(shù)據(jù)集作為一個(gè)整體加以處理,而不能將其視作多條記錄的集合咸产。這些操作要求在計(jì)算進(jìn)行過程中數(shù)據(jù)維持自己的狀態(tài)矢否。

? ? ? ? 需要處理大量數(shù)據(jù)的任務(wù)通常最適合用批處理操作進(jìn)行處理。無論直接從持久存儲(chǔ)設(shè)備處理數(shù)據(jù)集脑溢,或首先將數(shù)據(jù)集載入內(nèi)存,批處理系統(tǒng)在設(shè)計(jì)過程中就充分考慮了數(shù)據(jù)的量赖欣,可提供充足的處理資源屑彻。由于批處理在應(yīng)對(duì)大量持久數(shù)據(jù)方面的表現(xiàn)極為出色,因此經(jīng)常被用于對(duì)歷史數(shù)據(jù)進(jìn)行分析顶吮。

? ? ? ? 大量數(shù)據(jù)的處理需要付出大量時(shí)間社牲,因此批處理不適合對(duì)處理時(shí)間要求較高的場合。

Apache Hadoop

? ? ? ? Apache Hadoop是一種專用于批處理的處理框架悴了。Hadoop是首個(gè)在開源社區(qū)獲得極大關(guān)注的大數(shù)據(jù)框架搏恤∥ナ伲基于谷歌有關(guān)海量數(shù)據(jù)處理所發(fā)表的多篇論文與經(jīng)驗(yàn)的Hadoop重新實(shí)現(xiàn)了相關(guān)算法和組件堆棧,讓大規(guī)模批處理技術(shù)變得更易用熟空。

? ? ? ? 新版Hadoop包含多個(gè)組件藤巢,即多個(gè)層,通過配合使用可處理批數(shù)據(jù):

? ? ? ? HDFS:HDFS是一種分布式文件系統(tǒng)層息罗,可對(duì)集群節(jié)點(diǎn)間的存儲(chǔ)和復(fù)制進(jìn)行協(xié)調(diào)掂咒。HDFS確保了無法避免的節(jié)點(diǎn)故障發(fā)生后數(shù)據(jù)依然可用,可將其用作數(shù)據(jù)來源迈喉,可用于存儲(chǔ)中間態(tài)的處理結(jié)果绍刮,并可存儲(chǔ)計(jì)算的最終結(jié)果。

? ? ? ? YARN:YARN是Yet Another Resource Negotiator(另一個(gè)資源管理器)的縮寫挨摸,可充當(dāng)Hadoop堆棧的集群協(xié)調(diào)組件孩革。該組件負(fù)責(zé)協(xié)調(diào)并管理底層資源和調(diào)度作業(yè)的運(yùn)行。通過充當(dāng)集群資源的接口得运,YARN使得用戶能在Hadoop集群中使用比以往的迭代方式運(yùn)行更多類型的工作負(fù)載嫉戚。

? ? ? ? MapReduce:MapReduce是Hadoop的原生批處理引擎。

? ? ? 批處理模式

? ? ? ? Hadoop的處理功能來自MapReduce引擎澈圈。MapReduce的處理技術(shù)符合使用鍵值對(duì)的map彬檀、shuffle、reduce算法要求瞬女∏系郏基本處理過程包括:

? ? ? ? 從HDFS文件系統(tǒng)讀取數(shù)據(jù)集

? ? ? ? 將數(shù)據(jù)集拆分成小塊并分配給所有可用節(jié)點(diǎn)

? ? ? ? 針對(duì)每個(gè)節(jié)點(diǎn)上的數(shù)據(jù)子集進(jìn)行計(jì)算(計(jì)算的中間態(tài)結(jié)果會(huì)重新寫入HDFS)

? ? ? ? 重新分配中間態(tài)結(jié)果并按照鍵進(jìn)行分組

? ? ? ? 通過對(duì)每個(gè)節(jié)點(diǎn)計(jì)算的結(jié)果進(jìn)行匯總和組合對(duì)每個(gè)鍵的值進(jìn)行“Reducing”

? ? ? ? 將計(jì)算而來的最終結(jié)果重新寫入 HDFS

? ? ?優(yōu)勢(shì)和局限

? ? ? ? 由于這種方法嚴(yán)重依賴持久存儲(chǔ),每個(gè)任務(wù)需要多次執(zhí)行讀取和寫入操作诽偷,因此速度相對(duì)較慢坤学。但另一方面由于磁盤空間通常是服務(wù)器上最豐富的資源,這意味著MapReduce可以處理非常海量的數(shù)據(jù)集报慕。同時(shí)也意味著相比其他類似技術(shù)深浮,Hadoop的MapReduce通常可以在廉價(jià)硬件上運(yùn)行眠冈,因?yàn)樵摷夹g(shù)并不需要將一切都存儲(chǔ)在內(nèi)存中飞苇。MapReduce具備極高的縮放潛力,生產(chǎn)環(huán)境中曾經(jīng)出現(xiàn)過包含數(shù)萬個(gè)節(jié)點(diǎn)的應(yīng)用蜗顽。

? ? ? ? MapReduce的學(xué)習(xí)曲線較為陡峭布卡,雖然Hadoop生態(tài)系統(tǒng)的其他周邊技術(shù)可以大幅降低這一問題的影響,但通過Hadoop集群快速實(shí)現(xiàn)某些應(yīng)用時(shí)依然需要注意這個(gè)問題雇盖。

? ? ? ? 圍繞Hadoop已經(jīng)形成了遼闊的生態(tài)系統(tǒng)忿等,Hadoop集群本身也經(jīng)常被用作其他軟件的組成部件。很多其他處理框架和引擎通過與Hadoop集成也可以使用HDFS和YARN資源管理器崔挖。

? ? ? ?總結(jié)

? ? ? ? Apache Hadoop及其MapReduce處理引擎提供了一套久經(jīng)考驗(yàn)的批處理模型贸街,最適合處理對(duì)時(shí)間要求不高的非常大規(guī)模數(shù)據(jù)集庵寞。通過非常低成本的組件即可搭建完整功能的Hadoop集群,使得這一廉價(jià)且高效的處理技術(shù)可以靈活應(yīng)用在很多案例中薛匪。與其他框架和引擎的兼容與集成能力使得Hadoop可以成為使用不同技術(shù)的多種工作負(fù)載處理平臺(tái)的底層基礎(chǔ)捐川。

流處理系統(tǒng)


? ? ? ? 流處理系統(tǒng)會(huì)對(duì)隨時(shí)進(jìn)入系統(tǒng)的數(shù)據(jù)進(jìn)行計(jì)算。相比批處理模式蛋辈,是一種截然不同的處理方式属拾。流處理方式無需針對(duì)整個(gè)數(shù)據(jù)集執(zhí)行操作,而是對(duì)通過系統(tǒng)傳輸每個(gè)數(shù)據(jù)項(xiàng)執(zhí)行操作冷溶。

? ? ? ? 流處理中的數(shù)據(jù)集是“無邊界”的渐白,這就產(chǎn)生了幾個(gè)重要的影響:

? ? ? ? 完整數(shù)據(jù)集只能代表截至目前已經(jīng)進(jìn)入到系統(tǒng)中的數(shù)據(jù)總量。

? ? ? ? 工作數(shù)據(jù)集也許更相關(guān)逞频,在特定時(shí)間只能代表某個(gè)單一數(shù)據(jù)項(xiàng)纯衍。

? ? ? ? 處理工作是基于事件的,除非明確停止否則沒有“盡頭”苗胀。處理結(jié)果立刻可用襟诸,并會(huì)隨著新數(shù)據(jù)的抵達(dá)繼續(xù)更新。

? ? ? ? 流處理系統(tǒng)可以處理幾乎無限量的數(shù)據(jù)基协,但同一時(shí)間只能處理一條(真正的流處理)或很少量(微批處理歌亲,Micro-batch Processing)數(shù)據(jù),不同記錄間只維持最少量的狀態(tài)澜驮。雖然大部分系統(tǒng)提供了用于維持某些狀態(tài)的方法陷揪,但流處理主要針對(duì)副作用更少,更加功能性的處理(Functional processing)進(jìn)行優(yōu)化杂穷。

? ? ? ? 功能性操作主要側(cè)重于狀態(tài)或副作用有限的離散步驟悍缠。針對(duì)同一個(gè)數(shù)據(jù)執(zhí)行同一個(gè)操作會(huì)或略其他因素產(chǎn)生相同的結(jié)果,此類處理非常適合流處理耐量,因?yàn)椴煌?xiàng)的狀態(tài)通常是某些困難飞蚓、限制,以及某些情況下不需要的結(jié)果的結(jié)合體廊蜒。因此雖然某些類型的狀態(tài)管理通常是可行的趴拧,但這些框架通常在不具備狀態(tài)管理機(jī)制時(shí)更簡單也更高效。

? ? ? ? 此類處理非常適合某些類型的工作負(fù)載劲藐。有近實(shí)時(shí)處理需求的任務(wù)很適合使用流處理模式八堡。分析、服務(wù)器或應(yīng)用程序錯(cuò)誤日志聘芜,以及其他基于時(shí)間的衡量指標(biāo)是最適合的類型,因?yàn)閷?duì)這些領(lǐng)域的數(shù)據(jù)變化做出響應(yīng)對(duì)于業(yè)務(wù)職能來說是極為關(guān)鍵的缝龄。流處理很適合用來處理必須對(duì)變動(dòng)或峰值做出響應(yīng)汰现,并且關(guān)注一段時(shí)間內(nèi)變化趨勢(shì)的數(shù)據(jù)挂谍。

Apache Storm

? ? ? ? ?Apache Storm是一種側(cè)重于極低延遲的流處理框架,也許是要求近實(shí)時(shí)處理的工作負(fù)載的最佳選擇瞎饲。該技術(shù)可處理非常大量的數(shù)據(jù)口叙,通過比其他解決方案更低的延遲提供結(jié)果。

? ? ? 流處理模式

? ? ? ? Storm的流處理可對(duì)框架中名為Topology(拓?fù)洌┑腄AG(Directed Acyclic Graph嗅战,有向無環(huán)圖)進(jìn)行編排妄田。這些拓?fù)涿枋隽水?dāng)數(shù)據(jù)片段進(jìn)入系統(tǒng)后,需要對(duì)每個(gè)傳入的片段執(zhí)行的不同轉(zhuǎn)換或步驟驮捍。

? ? ? ? 拓?fù)浒?/p>

? ? ? ? Stream:普通的數(shù)據(jù)流疟呐,這是一種會(huì)持續(xù)抵達(dá)系統(tǒng)的無邊界數(shù)據(jù)。

? ? ? ? Spout:位于拓?fù)溥吘壍臄?shù)據(jù)流來源东且,例如可以是API或查詢等启具,從這里可以產(chǎn)生待處理的數(shù)據(jù)。

? ? ? ? Bolt:Bolt代表需要消耗流數(shù)據(jù)珊泳,對(duì)其應(yīng)用操作鲁冯,并將結(jié)果以流的形式進(jìn)行輸出的處理步驟。Bolt需要與每個(gè)Spout建立連接色查,隨后相互連接以組成所有必要的處理薯演。在拓?fù)涞奈膊浚梢允褂米罱K的Bolt輸出作為相互連接的其他系統(tǒng)的輸入秧了。

? ? ? ? Storm背后的想法是使用上述組件定義大量小型的離散操作跨扮,隨后將多個(gè)組件組成所需拓?fù)洹DJ(rèn)情況下Storm提供了“至少一次”的處理保證示惊,這意味著可以確保每條消息至少可以被處理一次好港,但某些情況下如果遇到失敗可能會(huì)處理多次。Storm無法確泵追#可以按照特定順序處理消息钧汹。

? ? ? ? 為了實(shí)現(xiàn)嚴(yán)格的一次處理,即有狀態(tài)處理录择,可以使用一種名為Trident的抽象拔莱。嚴(yán)格來說不使用Trident的Storm通常可稱之為Core Storm隘竭。Trident會(huì)對(duì)Storm的處理能力產(chǎn)生極大影響塘秦,會(huì)增加延遲,為處理提供狀態(tài)动看,使用微批模式代替逐項(xiàng)處理的純粹流處理模式尊剔。

? ? ? ? 為避免這些問題,通常建議Storm用戶盡可能使用Core Storm菱皆。然而也要注意须误,Trident對(duì)內(nèi)容嚴(yán)格的一次處理保證在某些情況下也比較有用挨稿,例如系統(tǒng)無法智能地處理重復(fù)消息時(shí)。如果需要在項(xiàng)之間維持狀態(tài)京痢,例如想要計(jì)算一個(gè)小時(shí)內(nèi)有多少用戶點(diǎn)擊了某個(gè)鏈接奶甘,此時(shí)Trident將是你唯一的選擇。雖不能充分發(fā)揮框架與生俱來的優(yōu)勢(shì)祭椰,但Trident提高了Storm的靈活性臭家。

? ? ? ? Trident拓?fù)浒?/p>

? ? ? ? 流批(Stream batch):這是指流數(shù)據(jù)的微批,可通過分塊提供批處理語義方淤。

? ? ? ? 操作(Operation):是指可以對(duì)數(shù)據(jù)執(zhí)行的批處理過程钉赁。

? ? ? 優(yōu)勢(shì)和局限

? ? ? ? 目前來說Storm可能是近實(shí)時(shí)處理領(lǐng)域的最佳解決方案。該技術(shù)可以用極低延遲處理數(shù)據(jù)臣淤,可用于希望獲得最低延遲的工作負(fù)載橄霉。如果處理速度直接影響用戶體驗(yàn),例如需要將處理結(jié)果直接提供給訪客打開的網(wǎng)站頁面邑蒋,此時(shí)Storm將會(huì)是一個(gè)很好的選擇姓蜂。

? ? ? ? Storm與Trident配合使得用戶可以用微批代替純粹的流處理。雖然借此用戶可以獲得更大靈活性打造更符合要求的工具医吊,但同時(shí)這種做法會(huì)削弱該技術(shù)相比其他解決方案最大的優(yōu)勢(shì)钱慢。話雖如此,但多一種流處理方式總是好的卿堂。

? ? ? ? Core Storm無法保證消息的處理順序束莫。Core Storm為消息提供了“至少一次”的處理保證,這意味著可以保證每條消息都能被處理草描,但也可能發(fā)生重復(fù)览绿。Trident提供了嚴(yán)格的一次處理保證,可以在不同批之間提供順序處理穗慕,但無法在一個(gè)批內(nèi)部實(shí)現(xiàn)順序處理饿敲。

? ? ? ? 在互操作性方面,Storm可與Hadoop的YARN資源管理器進(jìn)行集成逛绵,因此可以很方便地融入現(xiàn)有Hadoop部署怀各。除了支持大部分處理框架,Storm還可支持多種語言术浪,為用戶的拓?fù)涠x提供了更多選擇瓢对。

? ? ? 總結(jié)

? ? ? ? 對(duì)于延遲需求很高的純粹的流處理工作負(fù)載,Storm可能是最適合的技術(shù)胰苏。該技術(shù)可以保證每條消息都被處理硕蛹,可配合多種編程語言使用。由于Storm無法進(jìn)行批處理,如果需要這些能力可能還需要使用其他軟件妓美。如果對(duì)嚴(yán)格的一次處理保證有比較高的要求僵腺,此時(shí)可考慮使用Trident鲤孵。不過這種情況下其他流處理框架也許更適合壶栋。

Apache Samza

? ? ? ? Apache Samza是一種與Apache Kafka消息系統(tǒng)緊密綁定的流處理框架。雖然Kafka可用于很多流處理系統(tǒng)普监,但按照設(shè)計(jì)贵试,Samza可以更好地發(fā)揮Kafka獨(dú)特的架構(gòu)優(yōu)勢(shì)和保障。該技術(shù)可通過Kafka提供容錯(cuò)凯正、緩沖毙玻,以及狀態(tài)存儲(chǔ)。

? ? ? ? Samza可使用YARN作為資源管理器廊散。這意味著默認(rèn)情況下需要具備Hadoop集群(至少具備HDFS和YARN)桑滩,但同時(shí)也意味著Samza可以直接使用YARN豐富的內(nèi)建功能。

? ? ? 流處理模式

? ? ? ? Samza依賴Kafka的語義定義流的處理方式允睹。Kafka在處理數(shù)據(jù)時(shí)涉及下列概念:

? ? ? ? Topic(話題):進(jìn)入Kafka系統(tǒng)的每個(gè)數(shù)據(jù)流可稱之為一個(gè)話題运准。話題基本上是一種可供消耗方訂閱的,由相關(guān)信息組成的數(shù)據(jù)流缭受。

? ? ? ? Partition(分區(qū)):為了將一個(gè)話題分散至多個(gè)節(jié)點(diǎn)胁澳,Kafka會(huì)將傳入的消息劃分為多個(gè)分區(qū)。分區(qū)的劃分將基于鍵(Key)進(jìn)行米者,這樣可以保證包含同一個(gè)鍵的每條消息可以劃分至同一個(gè)分區(qū)韭畸。分區(qū)的順序可獲得保證。

? ? ? ? Broker(代理):組成Kafka集群的每個(gè)節(jié)點(diǎn)也叫做代理蔓搞。

? ? ? ? Producer(生成方):任何向Kafka話題寫入數(shù)據(jù)的組件可以叫做生成方胰丁。生成方可提供將話題劃分為分區(qū)所需的鍵。

? ? ? ? Consumer(消耗方):任何從Kafka讀取話題的組件可叫做消耗方喂分。消耗方需要負(fù)責(zé)維持有關(guān)自己分支的信息锦庸,這樣即可在失敗后知道哪些記錄已經(jīng)被處理過了。

? ? ? ? 由于Kafka相當(dāng)于永恒不變的日志妻顶,Samza也需要處理永恒不變的數(shù)據(jù)流酸员。這意味著任何轉(zhuǎn)換創(chuàng)建的新數(shù)據(jù)流都可被其他組件所使用,而不會(huì)對(duì)最初的數(shù)據(jù)流產(chǎn)生影響讳嘱。

? ? ? 優(yōu)勢(shì)和局限

? ? ? ? 乍看之下幔嗦,Samza對(duì)Kafka類查詢系統(tǒng)的依賴似乎是一種限制,然而這也可以為系統(tǒng)提供一些獨(dú)特的保證和功能沥潭,這些內(nèi)容也是其他流處理系統(tǒng)不具備的邀泉。

? ? ? ? 例如Kafka已經(jīng)提供了可以通過低延遲方式訪問的數(shù)據(jù)存儲(chǔ)副本,此外還可以為每個(gè)數(shù)據(jù)分區(qū)提供非常易用且低成本的多訂閱者模型。所有輸出內(nèi)容汇恤,包括中間態(tài)的結(jié)果都可寫入到Kafka庞钢,并可被下游步驟獨(dú)立使用。

? ? ? ? 這種對(duì)Kafka的緊密依賴在很多方面類似于MapReduce引擎對(duì)HDFS的依賴因谎。雖然在批處理的每個(gè)計(jì)算之間對(duì)HDFS的依賴導(dǎo)致了一些嚴(yán)重的性能問題基括,但也避免了流處理遇到的很多其他問題。

? ? ? ? Samza與Kafka之間緊密的關(guān)系使得處理步驟本身可以非常松散地耦合在一起财岔。無需事先協(xié)調(diào)风皿,即可在輸出的任何步驟中增加任意數(shù)量的訂閱者,對(duì)于有多個(gè)團(tuán)隊(duì)需要訪問類似數(shù)據(jù)的組織匠璧,這一特性非常有用桐款。多個(gè)團(tuán)隊(duì)可以全部訂閱進(jìn)入系統(tǒng)的數(shù)據(jù)話題,或任意訂閱其他團(tuán)隊(duì)對(duì)數(shù)據(jù)進(jìn)行過某些處理后創(chuàng)建的話題夷恍。這一切并不會(huì)對(duì)數(shù)據(jù)庫等負(fù)載密集型基礎(chǔ)架構(gòu)造成額外的壓力魔眨。

? ? ? ?直接寫入Kafka還可避免回壓(Backpressure)問題∧鹧回壓是指當(dāng)負(fù)載峰值導(dǎo)致數(shù)據(jù)流入速度超過組件實(shí)時(shí)處理能力的情況遏暴,這種情況可能導(dǎo)致處理工作停頓并可能丟失數(shù)據(jù)。按照設(shè)計(jì)执虹,Kafka可以將數(shù)據(jù)保存很長時(shí)間拓挥,這意味著組件可以在方便的時(shí)候繼續(xù)進(jìn)行處理,并可直接重啟動(dòng)而無需擔(dān)心造成任何后果袋励。

? ? ? ? Samza可以使用以本地鍵值存儲(chǔ)方式實(shí)現(xiàn)的容錯(cuò)檢查點(diǎn)系統(tǒng)存儲(chǔ)數(shù)據(jù)侥啤。這樣Samza即可獲得“至少一次”的交付保障,但面對(duì)由于數(shù)據(jù)可能多次交付造成的失敗茬故,該技術(shù)無法對(duì)匯總后狀態(tài)(例如計(jì)數(shù))提供精確恢復(fù)盖灸。

? ? ? ? Samza提供的高級(jí)抽象使其在很多方面比Storm等系統(tǒng)提供的基元(Primitive)更易于配合使用。目前Samza只支持JVM語言磺芭,這意味著它在語言支持方面不如Storm靈活赁炎。

? ? ? ? 總結(jié)

? ? ? ? 對(duì)于已經(jīng)具備或易于實(shí)現(xiàn)Hadoop和Kafka的環(huán)境,Apache Samza是流處理工作負(fù)載一個(gè)很好的選擇钾腺。Samza本身很適合有多個(gè)團(tuán)隊(duì)需要使用(但相互之間并不一定緊密協(xié)調(diào))不同處理階段的多個(gè)數(shù)據(jù)流的組織徙垫。Samza可大幅簡化很多流處理工作,可實(shí)現(xiàn)低延遲的性能放棒。如果部署需求與當(dāng)前系統(tǒng)不兼容姻报,也許并不適合使用,但如果需要極低延遲的處理间螟,或?qū)?yán)格的一次處理語義有較高需求吴旋,此時(shí)依然適合考慮损肛。

混合處理系統(tǒng):批處理和流處理


? ? ? ? 一些處理框架可同時(shí)處理批處理和流處理工作負(fù)載。這些框架可以用相同或相關(guān)的組件和API處理兩種類型的數(shù)據(jù)荣瑟,借此讓不同的處理需求得以簡化治拿。

? ? ? ? 如你所見,這一特性主要是由Spark和Flink實(shí)現(xiàn)的笆焰,下文將介紹這兩種框架劫谅。實(shí)現(xiàn)這樣的功能重點(diǎn)在于兩種不同處理模式如何進(jìn)行統(tǒng)一,以及要對(duì)固定和不固定數(shù)據(jù)集之間的關(guān)系進(jìn)行何種假設(shè)仙辟。

? ? ? ? 雖然側(cè)重于某一種處理類型的項(xiàng)目會(huì)更好地滿足具體用例的要求同波,但混合框架意在提供一種數(shù)據(jù)處理的通用解決方案。這種框架不僅可以提供處理數(shù)據(jù)所需的方法叠国,而且提供了自己的集成項(xiàng)、庫戴尸、工具粟焊,可勝任圖形分析、機(jī)器學(xué)習(xí)孙蒙、交互式查詢等多種任務(wù)项棠。

Apache Spark

? ? ? ? Apache Spark是一種包含流處理能力的下一代批處理框架。與Hadoop的MapReduce引擎基于各種相同原則開發(fā)而來的Spark主要側(cè)重于通過完善的內(nèi)存計(jì)算和處理優(yōu)化機(jī)制加快批處理工作負(fù)載的運(yùn)行速度挎峦。

? ? ? ? Spark可作為獨(dú)立集群部署(需要相應(yīng)存儲(chǔ)層的配合)香追,或可與Hadoop集成并取代MapReduce引擎。

? ? ? 批處理模式

? ? ? ? 與MapReduce不同坦胶,Spark的數(shù)據(jù)處理工作全部在內(nèi)存中進(jìn)行透典,只在一開始將數(shù)據(jù)讀入內(nèi)存,以及將最終結(jié)果持久存儲(chǔ)時(shí)需要與存儲(chǔ)層交互顿苇。所有中間態(tài)的處理結(jié)果均存儲(chǔ)在內(nèi)存中峭咒。

? ? ? ? 雖然內(nèi)存中處理方式可大幅改善性能,Spark在處理與磁盤有關(guān)的任務(wù)時(shí)速度也有很大提升纪岁,因?yàn)橥ㄟ^提前對(duì)整個(gè)任務(wù)集進(jìn)行分析可以實(shí)現(xiàn)更完善的整體式優(yōu)化凑队。為此Spark可創(chuàng)建代表所需執(zhí)行的全部操作,需要操作的數(shù)據(jù)幔翰,以及操作和數(shù)據(jù)之間關(guān)系的Directed Acyclic Graph(有向無環(huán)圖)漩氨,即DAG,借此處理器可以對(duì)任務(wù)進(jìn)行更智能的協(xié)調(diào)遗增。

? ? ? ? 為了實(shí)現(xiàn)內(nèi)存中批計(jì)算叫惊,Spark會(huì)使用一種名為Resilient Distributed Dataset(彈性分布式數(shù)據(jù)集),即RDD的模型來處理數(shù)據(jù)贡定。這是一種代表數(shù)據(jù)集赋访,只位于內(nèi)存中,永恒不變的結(jié)構(gòu)。針對(duì)RDD執(zhí)行的操作可生成新的RDD蚓耽。每個(gè)RDD可通過世系(Lineage)回溯至父級(jí)RDD渠牲,并最終回溯至磁盤上的數(shù)據(jù)。Spark可通過RDD在無需將每個(gè)操作的結(jié)果寫回磁盤的前提下實(shí)現(xiàn)容錯(cuò)步悠。

? ? ? 流處理模式

? ? ? ? 流處理能力是由Spark Streaming實(shí)現(xiàn)的签杈。Spark本身在設(shè)計(jì)上主要面向批處理工作負(fù)載,為了彌補(bǔ)引擎設(shè)計(jì)和流處理工作負(fù)載特征方面的差異鼎兽,Spark實(shí)現(xiàn)了一種叫做微批(Micro-batch)*的概念答姥。在具體策略方面該技術(shù)可以將數(shù)據(jù)流視作一系列非常小的“批”,借此即可通過批處理引擎的原生語義進(jìn)行處理谚咬。

? ? ? ? Spark Streaming會(huì)以亞秒級(jí)增量對(duì)流進(jìn)行緩沖鹦付,隨后這些緩沖會(huì)作為小規(guī)模的固定數(shù)據(jù)集進(jìn)行批處理。這種方式的實(shí)際效果非常好择卦,但相比真正的流處理框架在性能方面依然不足敲长。

? ? ? 優(yōu)勢(shì)和局限

? ? ? ? 使用Spark而非Hadoop MapReduce的主要原因是速度。在內(nèi)存計(jì)算策略和先進(jìn)的DAG調(diào)度等機(jī)制的幫助下秉继,Spark可以用更快速度處理相同的數(shù)據(jù)集祈噪。

? ? ? ?Spark的另一個(gè)重要優(yōu)勢(shì)在于多樣性。該產(chǎn)品可作為獨(dú)立集群部署尚辑,或與現(xiàn)有Hadoop集群集成辑鲤。該產(chǎn)品可運(yùn)行批處理和流處理,運(yùn)行一個(gè)集群即可處理不同類型的任務(wù)杠茬。

? ? ? ? 除了引擎自身的能力外月褥,圍繞Spark還建立了包含各種庫的生態(tài)系統(tǒng),可為機(jī)器學(xué)習(xí)澈蝙、交互式查詢等任務(wù)提供更好的支持吓坚。相比MapReduce,Spark任務(wù)更是“眾所周知”地易于編寫灯荧,因此可大幅提高生產(chǎn)力礁击。

? ? ? ? 為流處理系統(tǒng)采用批處理的方法,需要對(duì)進(jìn)入系統(tǒng)的數(shù)據(jù)進(jìn)行緩沖逗载。緩沖機(jī)制使得該技術(shù)可以處理非常大量的傳入數(shù)據(jù)哆窿,提高整體吞吐率,但等待緩沖區(qū)清空也會(huì)導(dǎo)致延遲增高厉斟。這意味著Spark Streaming可能不適合處理對(duì)延遲有較高要求的工作負(fù)載挚躯。

? ? ? ? 由于內(nèi)存通常比磁盤空間更貴,因此相比基于磁盤的系統(tǒng)擦秽,Spark成本更高码荔。然而處理速度的提升意味著可以更快速完成任務(wù)漩勤,在需要按照小時(shí)數(shù)為資源付費(fèi)的環(huán)境中,這一特性通乘踅粒可以抵消增加的成本越败。

? ? ? ? Spark內(nèi)存計(jì)算這一設(shè)計(jì)的另一個(gè)后果是,如果部署在共享的集群中可能會(huì)遇到資源不足的問題硼瓣。相比Hadoop MapReduce究飞,Spark的資源消耗更大,可能會(huì)對(duì)需要在同一時(shí)間使用集群的其他任務(wù)產(chǎn)生影響堂鲤。從本質(zhì)來看亿傅,Spark更不適合與Hadoop堆棧的其他組件共存一處。

? ? ? 總結(jié)

? ? ? ? Spark是多樣化工作負(fù)載處理任務(wù)的最佳選擇瘟栖。Spark批處理能力以更高內(nèi)存占用為代價(jià)提供了無與倫比的速度優(yōu)勢(shì)葵擎。對(duì)于重視吞吐率而非延遲的工作負(fù)載,則比較適合使用Spark Streaming作為流處理解決方案慢宗。

Apache Flink

? ? ? ? Apache Flink是一種可以處理批處理任務(wù)的流處理框架坪蚁。該技術(shù)可將批處理數(shù)據(jù)視作具備有限邊界的數(shù)據(jù)流,借此將批處理任務(wù)作為流處理的子集加以處理镜沽。為所有處理任務(wù)采取流處理為先的方法會(huì)產(chǎn)生一系列有趣的副作用。

? ? ? ? 這種流處理為先的方法也叫做Kappa架構(gòu)贱田,與之相對(duì)的是更加被廣為人知的Lambda架構(gòu)(該架構(gòu)中使用批處理作為主要處理方法缅茉,使用流作為補(bǔ)充并提供早期未經(jīng)提煉的結(jié)果)。Kappa架構(gòu)中會(huì)對(duì)一切進(jìn)行流處理男摧,借此對(duì)模型進(jìn)行簡化蔬墩,而這一切是在最近流處理引擎逐漸成熟后才可行的。

? ? ? 流處理模型

? ? ? ? Flink的流處理模型在處理傳入數(shù)據(jù)時(shí)會(huì)將每一項(xiàng)視作真正的數(shù)據(jù)流耗拓。Flink提供的DataStream API可用于處理無盡的數(shù)據(jù)流拇颅。Flink可配合使用的基本組件包括:

? ? ? ? Stream(流)是指在系統(tǒng)中流轉(zhuǎn)的,永恒不變的無邊界數(shù)據(jù)集

? ? ? ? Operator(操作方)是指針對(duì)數(shù)據(jù)流執(zhí)行操作以產(chǎn)生其他數(shù)據(jù)流的功能

? ? ? ? Source(源)是指數(shù)據(jù)流進(jìn)入系統(tǒng)的入口點(diǎn)

? ? ? ? Sink(槽)是指數(shù)據(jù)流離開Flink系統(tǒng)后進(jìn)入到的位置乔询,槽可以是數(shù)據(jù)庫或到其他系統(tǒng)的連接器

? ? ? ? 為了在計(jì)算過程中遇到問題后能夠恢復(fù)樟插,流處理任務(wù)會(huì)在預(yù)定時(shí)間點(diǎn)創(chuàng)建快照。為了實(shí)現(xiàn)狀態(tài)存儲(chǔ)竿刁,F(xiàn)link可配合多種狀態(tài)后端系統(tǒng)使用黄锤,具體取決于所需實(shí)現(xiàn)的復(fù)雜度和持久性級(jí)別。

? ? ? ? 此外Flink的流處理能力還可以理解“事件時(shí)間”這一概念食拜,這是指事件實(shí)際發(fā)生的時(shí)間鸵熟,此外該功能還可以處理會(huì)話。這意味著可以通過某種有趣的方式確保執(zhí)行順序和分組负甸。

? ? ? 批處理模型

? ? ? ? Flink的批處理模型在很大程度上僅僅是對(duì)流處理模型的擴(kuò)展流强。此時(shí)模型不再從持續(xù)流中讀取數(shù)據(jù)痹届,而是從持久存儲(chǔ)中以流的形式讀取有邊界的數(shù)據(jù)集。Flink會(huì)對(duì)這些處理模型使用完全相同的運(yùn)行時(shí)打月。

? ? ? ? Flink可以對(duì)批處理工作負(fù)載實(shí)現(xiàn)一定的優(yōu)化队腐。例如由于批處理操作可通過持久存儲(chǔ)加以支持,F(xiàn)link可以不對(duì)批處理工作負(fù)載創(chuàng)建快照僵控。數(shù)據(jù)依然可以恢復(fù)香到,但常規(guī)處理操作可以執(zhí)行得更快。

? ? ? ? 另一個(gè)優(yōu)化是對(duì)批處理任務(wù)進(jìn)行分解报破,這樣即可在需要的時(shí)候調(diào)用不同階段和組件悠就。借此Flink可以與集群的其他用戶更好地共存。對(duì)任務(wù)提前進(jìn)行分析使得Flink可以查看需要執(zhí)行的所有操作充易、數(shù)據(jù)集的大小梗脾,以及下游需要執(zhí)行的操作步驟择镇,借此實(shí)現(xiàn)進(jìn)一步的優(yōu)化逝她。

? ? ? 優(yōu)勢(shì)和局限

? ? ? ? Flink目前是處理框架領(lǐng)域一個(gè)獨(dú)特的技術(shù)临庇。雖然Spark也可以執(zhí)行批處理和流處理季惯,但Spark的流處理采取的微批架構(gòu)使其無法適用于很多用例疆虚。Flink流處理為先的方法可提供低延遲创葡,高吞吐率呕寝,近乎逐項(xiàng)處理的能力矿酵。

? ? ? ? Flink的很多組件是自行管理的改备。雖然這種做法較為罕見控漠,但出于性能方面的原因,該技術(shù)可自行管理內(nèi)存悬钳,無需依賴原生的Java垃圾回收機(jī)制盐捷。與Spark不同,待處理數(shù)據(jù)的特征發(fā)生變化后Flink無需手工優(yōu)化和調(diào)整默勾,并且該技術(shù)也可以自行處理數(shù)據(jù)分區(qū)和自動(dòng)緩存等操作碉渡。

? ? ? ? Flink會(huì)通過多種方式對(duì)工作進(jìn)行分許進(jìn)而優(yōu)化任務(wù)。這種分析在部分程度上類似于SQL查詢規(guī)劃器對(duì)關(guān)系型數(shù)據(jù)庫所做的優(yōu)化母剥,可針對(duì)特定任務(wù)確定最高效的實(shí)現(xiàn)方法滞诺。該技術(shù)還支持多階段并行執(zhí)行,同時(shí)可將受阻任務(wù)的數(shù)據(jù)集合在一起媳搪。對(duì)于迭代式任務(wù)铭段,出于性能方面的考慮,F(xiàn)link會(huì)嘗試在存儲(chǔ)數(shù)據(jù)的節(jié)點(diǎn)上執(zhí)行相應(yīng)的計(jì)算任務(wù)秦爆。此外還可進(jìn)行“增量迭代”序愚,或僅對(duì)數(shù)據(jù)中有改動(dòng)的部分進(jìn)行迭代。

? ? ? ? 在用戶工具方面等限,F(xiàn)link提供了基于Web的調(diào)度視圖爸吮,借此可輕松管理任務(wù)并查看系統(tǒng)狀態(tài)芬膝。用戶也可以查看已提交任務(wù)的優(yōu)化方案,借此了解任務(wù)最終是如何在集群中實(shí)現(xiàn)的形娇。對(duì)于分析類任務(wù)锰霜,F(xiàn)link提供了類似SQL的查詢,圖形化處理桐早,以及機(jī)器學(xué)習(xí)庫癣缅,還支持內(nèi)存計(jì)算。

? ? ? ? Flink能很好地與其他組件配合使用哄酝。如果配合Hadoop 堆棧使用友存,該技術(shù)可以很好地融入整個(gè)環(huán)境,在任何時(shí)候都只占用必要的資源陶衅。該技術(shù)可輕松地與YARN屡立、HDFS和Kafka 集成。在兼容包的幫助下搀军,F(xiàn)link還可以運(yùn)行為其他處理框架膨俐,例如Hadoop和Storm編寫的任務(wù)。

? ? ? ? 目前Flink最大的局限之一在于這依然是一個(gè)非痴志洌“年幼”的項(xiàng)目》俅蹋現(xiàn)實(shí)環(huán)境中該項(xiàng)目的大規(guī)模部署尚不如其他處理框架那么常見,對(duì)于Flink在縮放能力方面的局限目前也沒有較為深入的研究门烂。隨著快速開發(fā)周期的推進(jìn)和兼容包等功能的完善檩坚,當(dāng)越來越多的組織開始嘗試時(shí),可能會(huì)出現(xiàn)越來越多的Flink部署诅福。

? ? ? 總結(jié)

? ? ? ? Flink提供了低延遲流處理,同時(shí)可支持傳統(tǒng)的批處理任務(wù)拖叙。Flink也許最適合有極高流處理需求氓润,并有少量批處理任務(wù)的組織。該技術(shù)可兼容原生Storm和Hadoop程序薯鳍,可在YARN管理的集群上運(yùn)行咖气,因此可以很方便地進(jìn)行評(píng)估⊥诼耍快速進(jìn)展的開發(fā)工作使其值得被大家關(guān)注崩溪。

結(jié)論


? ? ? ? 大數(shù)據(jù)系統(tǒng)可使用多種處理技術(shù)。

? ? ? ? 對(duì)于僅需要批處理的工作負(fù)載斩松,如果對(duì)時(shí)間不敏感伶唯,比其他解決方案實(shí)現(xiàn)成本更低的Hadoop將會(huì)是一個(gè)好選擇。

? ? ? ? 對(duì)于僅需要流處理的工作負(fù)載惧盹,Storm可支持更廣泛的語言并實(shí)現(xiàn)極低延遲的處理乳幸,但默認(rèn)配置可能產(chǎn)生重復(fù)結(jié)果并且無法保證順序瞪讼。Samza與YARN和Kafka緊密集成可提供更大靈活性,更易用的多團(tuán)隊(duì)使用粹断,以及更簡單的復(fù)制和狀態(tài)管理符欠。

? ? ? ? 對(duì)于混合型工作負(fù)載,Spark可提供高速批處理和微批處理模式的流處理瓶埋。該技術(shù)的支持更完善希柿,具備各種集成庫和工具,可實(shí)現(xiàn)靈活的集成养筒。Flink提供了真正的流處理并具備批處理能力曾撤,通過深度優(yōu)化可運(yùn)行針對(duì)其他平臺(tái)編寫的任務(wù),提供低延遲的處理闽颇,但實(shí)際應(yīng)用方面還為時(shí)過早盾戴。

? ? ? ? 最適合的解決方案主要取決于待處理數(shù)據(jù)的狀態(tài),對(duì)處理所需時(shí)間的需求兵多,以及希望得到的結(jié)果尖啡。具體是使用全功能解決方案或主要側(cè)重于某種項(xiàng)目的解決方案,這個(gè)問題需要慎重權(quán)衡剩膘。隨著逐漸成熟并被接受衅斩,在評(píng)估任何新出現(xiàn)的創(chuàng)新型解決方案時(shí)都要考慮類似的問題。



譯自:Hadoop, Storm, Samza, Spark, and Flink: Big Data Frameworks Compared

譯者:大愚若智

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怠褐,一起剝皮案震驚了整個(gè)濱河市畏梆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奈懒,老刑警劉巖奠涌,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異磷杏,居然都是意外死亡溜畅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門极祸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慈格,“玉大人,你說我怎么就攤上這事遥金≡±Γ” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵稿械,是天一觀的道長选泻。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么滔金? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任色解,我火速辦了婚禮,結(jié)果婚禮上餐茵,老公的妹妹穿的比我還像新娘科阎。我一直安慰自己,他們只是感情好忿族,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布锣笨。 她就那樣靜靜地躺著,像睡著了一般道批。 火紅的嫁衣襯著肌膚如雪错英。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天隆豹,我揣著相機(jī)與錄音椭岩,去河邊找鬼。 笑死璃赡,一個(gè)胖子當(dāng)著我的面吹牛判哥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碉考,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼塌计,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了侯谁?” 一聲冷哼從身側(cè)響起锌仅,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎墙贱,沒想到半個(gè)月后热芹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惨撇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年剿吻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片串纺。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖椰棘,靈堂內(nèi)的尸體忽然破棺而出纺棺,到底是詐尸還是另有隱情,我是刑警寧澤邪狞,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布祷蝌,位于F島的核電站,受9級(jí)特大地震影響帆卓,放射性物質(zhì)發(fā)生泄漏巨朦。R本人自食惡果不足惜米丘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望糊啡。 院中可真熱鬧拄查,春花似錦、人聲如沸棚蓄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梭依。三九已至稍算,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間役拴,已是汗流浹背糊探。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留河闰,地道東北人科平。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像淤击,于是被迫代替她去往敵國和親匠抗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容