我们常常意识不到问题的存在,直到有人解决了这些问题
Hadoop MapReduce雖然已經(jīng)可以滿足大數(shù)據(jù)的應(yīng)用場(chǎng)景,但是其執(zhí)行速度和編程復(fù)雜度并不讓人們滿意。于是UC Berkeley的AMP Lab推出的Spark應(yīng)運(yùn)而生,Spark擁有更快的執(zhí)行速度和更友好的編程接口,在推出后短短兩年就迅速搶占MapReduce的市場(chǎng)份額,成為主流的大數(shù)據(jù)計(jì)算框架。
讀到這里請(qǐng)你先停一下,請(qǐng)給這段看似“沒(méi)毛病”的引子找找問(wèn)題。
不知道你意識(shí)到?jīng)]有,我在這段開頭說(shuō)的,“Hadoop MapReduce雖然已經(jīng)可以滿足大數(shù)據(jù)的應(yīng)用場(chǎng)景,但是其執(zhí)行速度和編程復(fù)雜度并不讓人們滿意”,這句話其實(shí)是錯(cuò)誤的。這樣說(shuō)好像可以讓你更加清晰地看到事物發(fā)展的因果關(guān)系,同時(shí)也可以暗示別人自己有洞察事物發(fā)展規(guī)律的能力。然而,這種靠事后分析的因果規(guī)律常常是錯(cuò)誤的,往往把結(jié)果當(dāng)作了原因。
事實(shí)上,在Spark出現(xiàn)之前,我們并沒(méi)有對(duì)MapReduce的執(zhí)行速度不滿,我們覺(jué)得大數(shù)據(jù)嘛、分布式計(jì)算嘛,這樣的速度也還可以啦。至于編程復(fù)雜度也是一樣,一方面Hive、Mahout這些工具將常用的MapReduce編程封裝起來(lái)了;另一方面,MapReduce已經(jīng)將分布式編程極大地簡(jiǎn)化了,當(dāng)時(shí)人們并沒(méi)有太多不滿。
真實(shí)的情況是,人們?cè)赟park出現(xiàn)之后,才開始對(duì)MapReduce不滿。原來(lái)大數(shù)據(jù)計(jì)算速度可以快這么多,編程也可以更簡(jiǎn)單。而且Spark支持Yarn和HDFS,公司遷移到Spark上的成本很小,于是很快,越來(lái)越多的公司用Spark代替MapReduce。也就是說(shuō),因?yàn)橛辛薙park,才對(duì)MapReduce不滿;而不是對(duì)MapReduce不滿,所以誕生了Spark。真實(shí)的因果關(guān)系是相反的。
這里有一條關(guān)于問(wèn)題的定律分享給你:我們常常意識(shí)不到問(wèn)題的存在,直到有人解決了這些問(wèn)題。
當(dāng)你去詢問(wèn)人們有什么問(wèn)題需要解決,有什么需求需要被滿足的時(shí)候,他們往往自己也不知道自己想要什么,常常言不由衷。但是如果你真正解決了他們的問(wèn)題,他們就會(huì)恍然大悟:啊,這才是我真正想要的,以前那些統(tǒng)統(tǒng)都是“垃圾”,我早就想要這樣的東西(功能)了。
所以頂尖的產(chǎn)品大師(問(wèn)題解決專家),并不會(huì)拿著個(gè)小本本四處去做需求調(diào)研,問(wèn)人們想要什么。而是在旁邊默默觀察人們是如何使用產(chǎn)品(解決問(wèn)題)的,然后思考更好的產(chǎn)品體驗(yàn)(解決問(wèn)題的辦法)是什么。最后當(dāng)他拿出新的產(chǎn)品設(shè)計(jì)(解決方案)的時(shí)候,人們就會(huì)視他為知己:你最懂我的需求(我最懂你的設(shè)計(jì))。
喬布斯是這樣的大師,Spark的作者馬鐵也是這樣的專家。
說(shuō)了那么多,我們回到Spark。Spark和MapReduce相比,有更快的執(zhí)行速度。下圖是Spark和MapReduce進(jìn)行邏輯回歸機(jī)器學(xué)習(xí)的性能比較,Spark比MapReduce快100多倍。
除了速度更快,Spark和MapReduce相比,還有更簡(jiǎn)單易用的編程模型。使用Scala語(yǔ)言在Spark上編寫WordCount程序,主要代碼只需要三行。
val textFile = sc.textFile(\u0026quot;hdfs://...\u0026quot;)val counts = textFile.flatMap(line =\u0026gt; line.split(\u0026quot; \u0026quot;)) .map(word =\u0026gt; (word, 1)) .reduceByKey(_ + _)counts.saveAsTextFile(\u0026quot;hdfs://...\u0026quot;)不熟悉Scala語(yǔ)言沒(méi)關(guān)系,我來(lái)解釋一下上面的代碼。
第1行代碼:根據(jù)HDFS路徑生成一個(gè)輸入數(shù)據(jù)RDD。
第2行代碼:在輸入數(shù)據(jù)RDD上執(zhí)行3個(gè)操作,得到一個(gè)新的RDD。
- 將輸入數(shù)據(jù)的每一行文本用空格拆分成單詞。
- 將每個(gè)單詞進(jìn)行轉(zhuǎn)換,word =\u0026gt; (word, 1),生成\u0026lt;Key, Value\u0026gt;的結(jié)構(gòu)。
- 相同的Key進(jìn)行統(tǒng)計(jì),統(tǒng)計(jì)方式是對(duì)Value求和,(_ + _)。
第3行代碼:將這個(gè)RDD保存到HDFS。
RDD是Spark的核心概念,是彈性數(shù)據(jù)集(Resilient Distributed Datasets)的縮寫。RDD既是Spark面向開發(fā)者的編程模型,又是Spark自身架構(gòu)的核心元素。
我們先來(lái)看看作為Spark編程模型的RDD。我們知道,大數(shù)據(jù)計(jì)算就是在大規(guī)模的數(shù)據(jù)集上進(jìn)行一系列的數(shù)據(jù)計(jì)算處理。MapReduce針對(duì)輸入數(shù)據(jù),將計(jì)算過(guò)程分為兩個(gè)階段,一個(gè)Map階段,一個(gè)Reduce階段,可以理解成是面向過(guò)程的大數(shù)據(jù)計(jì)算。我們?cè)谟肕apReduce編程的時(shí)候,思考的是,如何將計(jì)算邏輯用Map和Reduce兩個(gè)階段實(shí)現(xiàn),map和reduce函數(shù)的輸入和輸出是什么,這也是我們?cè)趯W(xué)習(xí)MapReduce編程的時(shí)候一再?gòu)?qiáng)調(diào)的。
而Spark則直接針對(duì)數(shù)據(jù)進(jìn)行編程,將大規(guī)模數(shù)據(jù)集合抽象成一個(gè)RDD對(duì)象,然后在這個(gè)RDD上進(jìn)行各種計(jì)算處理,得到一個(gè)新的RDD,繼續(xù)計(jì)算處理,直到得到最后的結(jié)果數(shù)據(jù)。所以Spark可以理解成是面向?qū)ο蟮拇髷?shù)據(jù)計(jì)算。我們?cè)谶M(jìn)行Spark編程的時(shí)候,思考的是一個(gè)RDD對(duì)象需要經(jīng)過(guò)什么樣的操作,轉(zhuǎn)換成另一個(gè)RDD對(duì)象,思考的重心和落腳點(diǎn)都在RDD上。
所以在上面WordCount的代碼示例里,第2行代碼實(shí)際上進(jìn)行了3次RDD轉(zhuǎn)換,每次轉(zhuǎn)換都得到一個(gè)新的RDD,因?yàn)樾碌腞DD可以繼續(xù)調(diào)用RDD的轉(zhuǎn)換函數(shù),所以連續(xù)寫成一行代碼。事實(shí)上,可以分成3行。
val rdd1 = textFile.flatMap(line =\u0026gt; line.split(\u0026quot; \u0026quot;))val rdd2 = rdd1.map(word =\u0026gt; (word, 1))val rdd3 = rdd2.reduceByKey(_ + _)RDD上定義的函數(shù)分兩種,一種是轉(zhuǎn)換(transformation)函數(shù),這種函數(shù)的返回值還是RDD;另一種是執(zhí)行(action)函數(shù),這種函數(shù)不再返回RDD。
RDD定義了很多轉(zhuǎn)換操作函數(shù),比如有計(jì)算map(func)、過(guò)濾filter(func)、合并數(shù)據(jù)集union(otherDataset)、根據(jù)Key聚合reduceByKey(func, [numPartitions])、連接數(shù)據(jù)集join(otherDataset, [numPartitions])、分組groupByKey([numPartitions])等十幾個(gè)函數(shù)。
我們?cè)賮?lái)看看作為Spark架構(gòu)核心元素的RDD。跟MapReduce一樣,Spark也是對(duì)大數(shù)據(jù)進(jìn)行分片計(jì)算,Spark分布式計(jì)算的數(shù)據(jù)分片、任務(wù)調(diào)度都是以RDD為單位展開的,每個(gè)RDD分片都會(huì)分配到一個(gè)執(zhí)行進(jìn)程去處理。
RDD上的轉(zhuǎn)換操作又分成兩種,一種轉(zhuǎn)換操作產(chǎn)生的RDD不會(huì)出現(xiàn)新的分片,比如map、filter等,也就是說(shuō)一個(gè)RDD數(shù)據(jù)分片,經(jīng)過(guò)map或者filter轉(zhuǎn)換操作后,結(jié)果還在當(dāng)前分片。就像你用map函數(shù)對(duì)每個(gè)數(shù)據(jù)加1,得到的還是這樣一組數(shù)據(jù),只是值不同。實(shí)際上,Spark并不是按照代碼寫的操作順序去生成RDD,比如“rdd2 = rdd1.map(func)”這樣的代碼并不會(huì)在物理上生成一個(gè)新的RDD。物理上,Spark只有在產(chǎn)生新的RDD分片時(shí)候,才會(huì)真的生成一個(gè)RDD,Spark的這種特性也被稱作惰性計(jì)算。
另一種轉(zhuǎn)換操作產(chǎn)生的RDD則會(huì)產(chǎn)生新的分片,比如reduceByKey,來(lái)自不同分片的相同Key必須聚合在一起進(jìn)行操作,這樣就會(huì)產(chǎn)生新的RDD分片。實(shí)際執(zhí)行過(guò)程中,是否會(huì)產(chǎn)生新的RDD分片,并不是根據(jù)轉(zhuǎn)換函數(shù)名就能判斷出來(lái)的,具體我們下一期再討論。
總之,你需要記住,Spark應(yīng)用程序代碼中的RDD和Spark執(zhí)行過(guò)程中生成的物理RDD不是一一對(duì)應(yīng)的,RDD在Spark里面是一個(gè)非常靈活的概念,同時(shí)又非常重要,需要認(rèn)真理解。
當(dāng)然Spark也有自己的生態(tài)體系,以Spark為基礎(chǔ),有支持SQL語(yǔ)句的Spark SQL,有支持流計(jì)算的Spark Streaming,有支持機(jī)器學(xué)習(xí)的MLlib,還有支持圖計(jì)算的GraphX。利用這些產(chǎn)品,Spark技術(shù)棧支撐起大數(shù)據(jù)分析、大數(shù)據(jù)機(jī)器學(xué)習(xí)等各種大數(shù)據(jù)應(yīng)用場(chǎng)景。
我前面提到,頂尖的產(chǎn)品設(shè)計(jì)大師和問(wèn)題解決專家,不會(huì)去詢問(wèn)人們想要什么,而是分析和觀察人們的做事方式,從而思考到更好的產(chǎn)品設(shè)計(jì)和問(wèn)題解決方案。
但是這種技巧需要深邃的觀察力和洞察力,如果沒(méi)有深度的思考,做出的東西就會(huì)淪為異想天開和自以為是。要知道大眾提出的需求雖然也無(wú)法觸及問(wèn)題的核心,但是好歹是有共識(shí)的,大家都能接受,按這種需求做出的東西雖然平庸,但是不至于令人厭惡。
而缺乏洞見(jiàn)的自以為是則會(huì)違反常識(shí),讓其他人本能產(chǎn)生排斥感,進(jìn)而產(chǎn)生對(duì)立情緒。這種情緒之下,設(shè)計(jì)沒(méi)有了進(jìn)一步改進(jìn)的基礎(chǔ),最后往往成為悲劇。這兩年在所謂互聯(lián)網(wǎng)思維的鼓吹下,一些缺乏專業(yè)技能的人,天馬行空創(chuàng)造需求,受到質(zhì)疑后公開批評(píng)用戶,也是讓人倍感驚詫。
我們?cè)谧约旱墓ぷ髦?#xff0c;作為一個(gè)不是頂尖大師的產(chǎn)品經(jīng)理或工程師,如何做到既不自以為是,又能逐漸擺脫平庸,進(jìn)而慢慢向大師的方向靠近呢?
有個(gè)技巧可以在工作中慢慢練習(xí):不要直接提出你的問(wèn)題和方案,不要直接說(shuō)“你的需求是什么?”“我這里有個(gè)方案你看一下”。
直向曲中求,對(duì)于復(fù)雜的問(wèn)題,越是直截了當(dāng)越是得不到答案。迂回曲折地提出問(wèn)題,一起思考問(wèn)題背后的規(guī)律,才能逐漸發(fā)現(xiàn)問(wèn)題的本質(zhì)。通過(guò)這種方式,既能達(dá)成共識(shí),不會(huì)有違常識(shí),又可能產(chǎn)生洞見(jiàn),使產(chǎn)品和方案呈現(xiàn)閃光點(diǎn)。
- 你覺(jué)得前一個(gè)版本最有意思(最有價(jià)值)的功能是什么?
- 你覺(jué)得我們這個(gè)版本應(yīng)該優(yōu)先關(guān)注哪個(gè)方面?
- 你覺(jué)得為什么有些用戶在下單以后沒(méi)有支付?
作者介紹
李智慧,極客時(shí)間《從0開始學(xué)大數(shù)據(jù)》專欄講師,同程藝龍交通首席架構(gòu)師、Apache Spark源代碼貢獻(xiàn)者,長(zhǎng)期從事大數(shù)據(jù)、大型網(wǎng)站架構(gòu)的研發(fā)工作,曾擔(dān)任阿里巴巴技術(shù)專家、Intel亞太研發(fā)中心架構(gòu)師、宅米和WiFi萬(wàn)能鑰匙CTO,有超過(guò)6年的線下咨詢、培訓(xùn)經(jīng)驗(yàn),著有暢銷書《大型網(wǎng)站技術(shù)架構(gòu):核心原理與案例分析》。
總結(jié)
以上是生活随笔為你收集整理的我们常常意识不到问题的存在,直到有人解决了这些问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 别人家的程序员是如何使用 Java 进行
- 下一篇: idea编辑springboot,如何打