[MOOCS:edx]BerkeleyX CS100.1x- Introduction to Big Data with Apache Spark (三)

image

前言

剩下兩週了,不過家中寶貝誕生.必須要把時間做更好的調配,才能完成這個課程.

相關文章

edx 課程網址在這裡 https://www.edx.org/course/introduction-big-data-apache-spark-uc-berkeleyx-cs100-1x

Lecture 7 Data Management

  • Data Clean: Deal with:
    • Missing Data
    • Entity Resolution
    • Unit mismatch
  • 對於現實世界中數值可能出現的Dirty Data分為以下各種:
    • 失真(distortion): 當發現在連續作業中的某段資料不見的時候.
    • 選擇性偏差(Selection Bias):由於樣本的選擇不同,所以得到差異相當大的數值.比如說訪問政黨傾向不同得民眾.這裡有更詳細資料
    • Left and Right Censorship: 由於樣本不斷地來來去去,不能知道樣本是否有跑完所有採樣流程.
    • 相依的(Denpendence): 每個樣本應該是比次獨立,但是有一些沒有而造成資料的偏差.
  • Data Gathering的重要性:
    • 資料在取得的時候存在許多發生錯誤的可能性,比如說硬體或軟體的問題或是欄位的問題..等等 若是能在取得資料的時候做一定程度的驗證,可以讓資料精確度更高.
  • 其他名詞解釋:
    • Big rot: 資料超過一定時間的沒有數值跟精準度.
  • Data Delivery可能發生的問題與解決方式:
    • 資料遺失或是毀損:
      • 透過可信賴的傳輸方式或是透過Relay,也可以增加checksum來增加資料傳遞的可信任程度.
    • 資料來源的相依性與可信任程度:
      • 必須跟資料提供者有相當程度協調與協議.

Lecture 8 Exploratory Data Analysis and Machine Learning

  • 敘述性統計(Descriptice Statistics): 透過統計數量來對事件作敘述,比如說,本班的成績平均.
  • 推論性統計(Inferencial Statistics): 透過收集到的統計數字,對事件作一定的推論.比如說,選前問卷調查.

  • 探索性數據分析(Explortory Data Analysis): 透過先行的探索來進行數據的分析,進行的活動可能有以下數種:
    • Visualizing the data distributions
    • Calculating summary statistics for the data
    • Examining the distributions of the data
  • Rhine Paradox: 找了一千個人來猜連續十張為藍色或紅色的卡片.進而判斷出不能告訴超能力的人他有超能力的心理分析結果.
    • Rhine’s Error: 但是真正的錯誤是,由於要猜測10張完全顏色一樣的機率為1 / 2^10 =>(1/1024) 也就是說一千個人要猜對一次也不到1個.其實要講解的是對於數據的不清楚造成錯誤的結論.
  • Spark Machine Learning Toolkit(mllib): 提供許多功能比如說分類與回歸分析或是一些數值分析的工具.

Lab3

這次的Lab3更加深難度的要讓我們學習Text Analysis 跟 Entity Resolution並且有提到“詞袋模型”(Bag-of-words model),裡面有幾個比較需要注意的地方:

關於 python dictionary 的 lambda:

這次比較困擾我的,其實是Python 的dict lambda

//建立一個新的map,其結果是 key in MapA value 是 MapA[key]+ MapB[key]
newDict = dict()
for k in MapA:
    newDict[k] = MapA[k] + MapB[k]

//可以用Lambda表示
newDict = {k: MapA[k]+MapB[k] for k in MapA}

很多題目都只有給一個 但是要做的事情太多,只得用lambda來思考.這個部分需要相當大量的腦力,蠻希望能有機會找找到更漂亮的解答.

關於一些Apache Spark查詢的優化方式:

由於不少人的查詢方式有點慢,造成auto-grader 發生錯誤,於是學校方面發了一些聲明來指導大家正確的使用他:

  • 關於找出最大的幾個數值的部分:

      #不要使用python的方式來排序,
      for i in vendorRDD.collect():
          measure len() to find biggest X
    
      #使用spark的action來找,放在記憶體跑會比較快.,
      vendorRDD.takeOrdered(helper function)
    
  • 關於聯集合的部分:

      #不要使用python的集合合併
      unionRDD = sc.parallelize(A.collect()+B.collect())
      #直接使用 union
      A.union(B)
    
  • 關於加總的部分

      #使用python的list家總是比較慢的.
      sum = sum(RDD.collect())
      #直接使用spark action裡面的加總
      RDD.sum() 
    

心得

關於“詞袋模型”(Bag-of-words model),一開始真的完全搞不懂這是在幹嘛.不過透過一步步地完成每一個小函式,最後組成完整的功能.也慢慢了解這個的原理.

這次由於中間卡著家中小寶貝的誕生,所以整個作業無法順利的全部做完.只能先把3/4的作業先弄完了. 不過這次的作業題目有夠難懂,主要時間都花在了解題目與思考提到到底要我們完成什麼.

最後,其實這週的lab3課程相當有趣,每個練習的排練方式也有提到一些些的原理.整個課程安排方式讓我回想到學習Scala的時候的學習脈絡,這大概也是學習FP的好處吧.

參考鏈結:

[MOOCS:edx]BerkeleyX CS100.1x- Introduction to Big Data with Apache Spark (二)

image

前言

這一篇筆記主要是針對EDX上面的課程: BerkeleyX: CS100.1x Introduction to Big Data with Apache Spark第三個禮拜的部分.剩下兩個禮拜而已… 加油!!

相關文章

edx 課程網址在這裡 https://www.edx.org/course/introduction-big-data-apache-spark-uc-berkeleyx-cs100-1x

Lecture 5

這一個章節主要是講解關於semi-structure資料結構與使用的方式. semi-structured資料主要講解就是一些類似XML或是Tag的資料結構.他有以下的缺點:

  • 各個欄位間可能存在不一致
  • 各個資料格式可能不盡相同(有的用英鎊有的用歐元)
  • 各個欄位內容可能不一致 (walmart <-> wal-mart)

針對這樣的缺點,semi-structured資料使用起來雖然簡單,但是存在者某些程度上的挑戰與風險. 此外這一章節也討論了,資料讀取的速度與效能. 幾個重點紀錄一下:

  • 對於壓縮格式的檔案讀取,讀取會比寫入快,
  • 而Binary IO會比 Text file 快,但是Text file 壓縮後比較小(壓縮比大)
  • LZ4壓縮比跟讀取速度都相當優秀.

Lecture 6

這一張主要講解的是Structured Data,也就是主要講解關於RDBMS相關的部分.這裏主要提到就是join與各種join的計算方式. 主要要注意的就是要如何的應用 spark join.

Lab2

比起Lab1來說,Lab2的份量實在是多了很多. 案例是分析一個月的Apache Log 透過Spark的一些操作可以分析一些有用的數據. 由於資料量也變大,這次的每個小案例,需要花上比較多的時間來執行.

關於regular expression的grouping

這邊有提到regular expression 的grouping,方法就可以幫你把一行字只要符合的狀況下就會切成一個Array來處理. 這裏用一個簡單的案例:

    test_string = "[aa bbb ccc]"
    match = re.search('^[(\S*) (\S*) (\S*))]', test_string)
    #match[1] = aa, match[2] = bb, match[3] = ccc

常用到的幾個計算方式

這裏有一些常用到的計算流程很適合做筆記:

紀錄某個資料出現個數

假設要計算某個錯誤資料每天出現幾次,計算方式可以如下:

#將錯誤資料變成tuple (2015-06-15, 1), (2015-06-16, 1)....
errDateCountPairTuple = errRecords.map(lambda data: (data.datetime, 1) )

#將錯誤資料透過reduceByKey之後,然後將每一個加總.
errDateSum = errDateCountPairTuple.reduceByKey(lambda a,b: a+b)

#排序
errDateSort = errDateSum.sortByKey()

如果要畫圖得時候

#X軸
errDateSort.map(lambda (key, value): key).collect()
#Y軸
errDateSort.map(lambda (key, value): value).collect()

想要取得top5

#想要數字多的在前面,使用-1 如果要少的在前面 就使用+1
errDateSort.takeOrdered(5, lambda s: -1 * s[1])

這大概是比較常用的幾個,此外也有幾個function 需要注意. 不外乎是 distinct()cache(), 如果出現任何問疑的時候,也建議趕快把資料印出五個來debug

#檢查如果有誤
errDateSort.take(5)    

心得整理:

這一次作業的資料量已經有點大,而且裡面的題目也有點多. (大約有20~30題) 每一個運算都要跑好久才有結果.

以下是我的心得:

  1. 跑很久…
  2. 錯了再一次. 又要很久…
  3. 沒想好… 就跑… 真的要很久…..
  4. 不小心搞掛系統… 全部重跑.. 會更久……

此外,由於使用ipynb來單步執行作業,繳交作業前也要確認你的ipynb沒有任何的warning跟error.就算是之前不小心跑出來也要讓他都成功才能繳交作業.

參考鏈結:

  • TBD

[MOOCS:edx]BerkeleyX CS100.1x- Introduction to Big Data with Apache Spark (一)

image

前言

之前學習MIT關於分散式系統的部分,其實對於MapReduce與BigData的部分還是一知半解.這一堂課似乎是大家所期盼的課程,所以來學習.其實課程的節奏算是合適,我想整個Loading也不會太重.

相關文章

edx 課程網址在這裡 https://www.edx.org/course/introduction-big-data-apache-spark-uc-berkeleyx-cs100-1x

課程筆記

本堂課的目標

edx給的官方目標:

  • 學習關於 Data Science的定義與本質
  • 如何使用 Data Science
  • 學習 Apache Spark

我自己的目標:

  • 瞭解 Data Science
  • 瞭解 Big Data相關應用
  • 學習並且了解 Apache Spark

WEEK1 (Lecture 1/2)

主要是設定環境跟一些 Big Daa的簡介,內容其實相當的淺顯易懂.

  • 環境設定方面:
  • Tranditional Machine Learning(以下簡稱: Machine Learning) 與 Data Science的差異:
    • Machine Learning為了建立有效的Model而Data Science使用建立好的models來分析資料
    • Data Science的產出會是一個BI (Business Intellegence)而Machine Learning 產生是一個數據良好的模型.
  • Data Science 流程:
    • 取得資料
    • 整理資料 (ETL: Extract-Transform-Load)
    • 分析資料
  • Data Science實際上可能由於突變因子造成數據不可信任
    • ex: 新聞與事件造成Google Search string 分析失誤
    • 解決方式: 移除該因子所造成的髒資料(Dirty Data),重新跑運算

WEEK2 (Lecture 3/4)

image

(Spark: 組成圖來源Spark 官網)

本週進度主要是介紹關於Apache Spark的優點(相較於 Hadoop MapReduce)

  • 關於Map Reduce的原理與方法
  • Cluster Computer最困難的莫過於處理:
    • (1) 把工作分散給各個機器
    • (2) 處理某些機器的fail或是過於緩慢的速度
  • 緩慢回應(slow)與失效節點(fail)處理方式: 重啟另外的節點,把運算轉移到新節點
  • Apache Spark 與 Hadoop MapReduce的差異:
    • 使用In-Memory Data Shading: (最大差異)
      • 將儲存到Hard disk的資料,全部放到記憶體上 (由於記憶體的成本逐漸降低)
    • 新的資料結構RDDs(Relient Distributed Datasets)
      • 具有track lineage information 可以發現並且修復某些資料
      • 建立後不能更改,但是可以根據已經存在的RDDs修改並建立新的
      • 支援Parallel處理下的資料集合
    • Generalized pattern, Lazy Evaluation, lower overhead and less expensive shuffles

關於RDD的相關程式碼

RDD 宣告
    data = [1, 2, 3, 4, 5]
    rdd = sc.parallelize(data, 4)

這段程式碼有以下特點:

  • 建立RDD,並且具有4 個 partition
  • 根據 Lazy Evaluation 他不會執行任何動作.只是建立RDD

     distFile = sc.textFile("...", 4)
    
  • 由檔案讀入並且,建立四個partition的RDD
  • 每一行事當成一個Element
Transformation

Spark 支援至少以下數種tranformations

  • map
  • filter
  • distinct
  • flatMap

而以上的tranformation並且也支援lambda,也就是說可以有以下數種處理:

    data = [1, 2, 3, 4]
    rdd = sc.parallelize(data, 4)

以下語法都使用同樣的rdd:

    rdd.map(lambda x: x*2)
    # 轉成一個map [1, 2, 3, 4] -> [2, 4, 6, 8]

若是改成filter

    rdd.filter(lambda x: x%2 = 1)
    # 轉成 [1, 3]

flatMap是一個會把所有set 切成平面

    rdd.flatMap(lambda x:[x, x+3])
    # 轉成 [ [0, 3], [1. 4], [2. 5], [3, 6], [4, 7]] => [0, 1, 2, 3, 3, 4, 4, 5, 6, 7]

切記: transformation 並不會馬上執行

Action

透過Action,Spark才會去執行transformation 並且把結果傳回給driver. 這是唯一能拿到結果的方式.

Spark 支援以下幾種的 Action:

  • reduce: 可以傳回所有的集合總和
  • take(n): 只拿前面n個結果
  • collect(): 把整個集合傳回
  • takeOrdered(n, func): 拿回符合func的前面n個結果,相當有用的action
Caching

想要避免action跑完後,需要原始的資料,可以透過 cache來把資料先暫存起來.記住,他一樣是屬於lazy evaluation所以是不會執行.

data = [1, 2, 3, 4, 5]
rdd = sc.parallelize(data, 4)
#create cache並且儲存 x*2 的結果
c1 = rdd.map(lambda x: x*2).cache()
#將rdd修改成 x= x*3
ret1 =rdd.map(lambda x: x*3).take(3)
print ret1
#此時cache依舊是舊的資料,可以直接開始其他action.
print c1.collect()
RDD Lifecycle
  • RDD create
    • sc.parallelize() or sc.textFile
    • transform 會將RDD製造新的副本出來… (Lazy create)
  • Action 之後,RDD就會結束.. 除非你有用cache 把RDD複製一份起來…
Shared Variables

rdd的function closure稱為worker,worker彼此間是無法溝通的.唯一能夠讓worker與driver溝通的方式就是透過以下兩種shared variables. (其實跟OpenCL很類似)

根據方向上而言,可以分為以下兩種:

  • Driver -> Worker (Broadcast)
    • Driver將read-only資料,傳送給各個worker
  • Worker -> Driver (Accumulator)
    • Worker將各個計算結果傳回給Driver這裏的資料是Write-only
    • Accumulator 只能在worker存取,並且每次worker只能寫一次

LAB1 Word Count###

透過iPython Notebook的Lab作業,因為是一步一步地執行.其實是相當的簡單.而且,就算真的看不懂要幹嘛~其實看下一個檢查的地方,就能了解你需要做什麼事情.幾個需要注意的地方:

  • 需要了解mapreduceByKey真正的差異在哪裡. 尤其是面對 key-value資料的處理上, map會一個個的iterate 但是reduceByKey 會已經透過key把重複的抓過來這個function比對.
  • 要注意到,每一個transform 與 action的關係,由於action 是一個closure所以不要把action 結果帶去另外一個transform
  • 對於我而言,一開始常犯的錯誤是: 把 map當作是filter來使用. 要注意的是:
    • map 會 iterator 每一個元素並且輸出結果.
    • filter 才會把符合function的放入你的結果中.
  • Lab1 整體很簡單,依照教學與只是可以做簡單的word count概念的功能.不過卡住我最久的竟然是regular expression,我是用regulex來幫助我了解與分析結果.

image

一個regular expression 的圖示,去除掉頭尾的空白與所有字串中的非字元與空白的字.

參考鏈結

[MOOCS][Golang]MIT6_824 Distributed Systems Week2(Lec2/Lab2B)

http://i.stack.imgur.com/MUtmL.png

(圖片: FDS的優化示意圖,由這裡來的)

##前言:

到了第二個禮拜,其實卡了很久在Lab2b裡面.主要不是因為要判斷的case太多,而是希望把每次的test case找到在論文中的理由或是整個學術上的依據.

MIT 6.824 分散式系統 系列文章

6.824: Distributed Systems

##論文-Flat Datacenter Storage

這是微軟在2012發表的新的分散式計算系統FDS,號稱可以在60秒處理141GB的資料,打敗了當初Yahoo所創下的紀錄.

FDS組成

FDS為了要達到速度快,把繁瑣的檔案系統移除.整個組成相當的簡單 (Blob 與 Tract)

Blob:

Blob 是FDS系統裡面的構成元件.每一個Blob由數個Tract所組成的.

  • 一個Blob 可以包含若干個Tract
  • 一個Blob 擁有一個唯一的GUID

其中Blob 提供以下的API:

  • CreateBlob
  • OpenBlob
  • DeleteBlob
  • CloeBlob

Tract:

FDS裡面最基本的元素.

  • Tract的檔案大小是固定的(預設是8MB)

所有的Tracts 是透過 TractServer來管理,以下為Tract 相關的API:

  • GetBlobSize
  • ExtendBlobSize
  • WriteTract
  • ReadTract
  • WriteTract
  • GetSimultaneousLimit

實際運作上:

  • Blob 並不需要放在同一台電腦上
  • 為了達到速度快,可以把tract放在不同的儲存媒體上.達到類似Raid-0的效果.
  • 用來索引各個tract位置的是TLT(Tract Locator Table)而Metadata Server就是管理TLT的伺服器.

這一篇對於組成的部分有更詳細的解釋

FDS的備份

##第二週下半課程: ##關於Lab2 Part B:he primary/backup key/value service

這一次的作業相當的有趣,由於上一次要識做一個Server與Client間的分派者或是說控制者的角色(稱為Viewserver). 而這次要做的就是另外兩個角色 PBServer 與 Client.

###幾個注意地方:

以下列出幾個比較基礎的地方:

  • PBServer 與 Client 與 ViewServer三方的溝通都必須透過RPC call
  • RPC call rpcname必須注意是要Class.Api. 舉例而言: ViewServer.Ping
  • Client 每個動作都需要先去問ViewServer目前的primary

###開始流程:

  • 完成Server的Get()Put()Ping() (Ping必須在Tick裡面)

  • 每個transaction 必須要透過 primary 把結果傳給 backup ~
  • primary/backup要有傳遞備份資料與互相溝通的RPC 要新增不少個
  • Server需要判別自己的角色是primary或是backup (可以使用 ViewServer.Getme來判別)
  • Server與Client溝通原則:
    • 每一個Client的command,在得到reply == OK 前,必須要不斷地送.
    • 相反的,Server必須要遵循at-most-once原則,要過濾掉重複的request
    • client 不能在每次Get/Put去跟ViewServer詢問目前誰是primary,除非你認為primary 已經死了.
      • 時間內沒回覆?
  • 角色的準則裡面:
    • Primary:
    • Backup:
      • 不能直接回覆client需求,而要回復錯誤

Lab2A 的Client (也就是身為 PBServer的角色) 需要知道自己的所扮演的角色 (Primary/Backup)

  • Get Arg 增加欄位判別需求是來自 server/client 是 primary 才需要ack back
  • 這樣可以避免寫Lab2B 的時候,造成Lab2A的Go test failed.

有趣的思維是:

  • 你必須同時考慮三個角色 (Client/PbServer/Viewserver) 交互關係
  • 必須確保 Lab2A / Lab2B 的測試不能有誤… (相互干擾是一定會的,寫完要回頭看……回頭測試)

資料的同步:

  • Backup剛起來的時候(或是每個一段時間) 需要從Primary備份所有資料庫
  • 每一次的資料變動 (在這個例子裡面是 Put發生的時候),需要馬上把資料傳給Backup

TestBasicFail 經驗分享

你需要完成以下:

image

  1. Remus的Fig1 流程(參考以上):
    1. 定期需要從 Primary -> Backup 所有資料庫 (自行新增RPC)
    2. 每個command 在Primary 完成後,需要先把結果傳給Backup,然後才傳給Client
  2. PBServer 必須知道自己是 Primary 還是 Backup 並且做相關的 Init
  3. Client需要做Repease Request 直到結果是正確的.(注意 每次RPC request 最好有間隔)

你還不需要做:

  1. Hash Put
  2. Repeat AtOnce (後面的測試會有)

TestAtMostOnce passed, 經驗分享:

  1. Client 需要不斷的send request 如果沒有收到result 或是收到空的result
  2. Server 需要過濾重複的指令,並且傳送之前的結果.
    • 所以你需要記住之前的指令與參數確保指令重複.
    • 需要儲存上一次結果.重複指令就回傳
    • 此外,對於重複指令不需要傳到Backup
  3. 忘了提一下,關於Hash的部分演算法是: Hash_Value = hash(Previous_Value_String + Currently_Value_String )

TestFailPut/TestConcurrentSame/TestConcurrentSameUnreliable passed, 經驗分享:

  1. 重點部分, 當client 與primary 溝通,如果發現疑似primary掛掉的狀態.需要跟viewserver詢問新的primary.

心得:

對於FDS的理解還算粗淺,希望隨著課程的了解能夠瞭解更多的資料.而Lab2的作業,整個作業還沒寫完,會持續更新相關的資料.

##參考文章:

[Golang]跟效能優化有關的視覺化工具(gcvis與pprof)

前言:

架設好主機後,接下來開始就是要優化效能.其實有很多人建議了不少的優化與調整工具,不過這裡還是使用兩個視覺化可以很快調整的工具.

  • gcvis: 由Dave Cheney所開發的工具,可以很清楚的觀察GC(Garbage Collection)發生的時間點與Heap的大小,讓你可以了解系統由於GC消耗的多少的系統資源.
  • pprof:這個系統build-in的工具,可以讓你產生每個function所產生的方塊圖可以讓你清楚找出系統裡面的bottleneck.

這裏只是簡單的使用流程與心得,不過應該會有更多的資料補充.

關於gcvis

image

安裝與使用

  • go get github.com/davecheney/gcvis
  • 使用相當簡單 gcvis YOUR_APP -index -http=:6060

就會打開一個網頁顯示目前的heap與GC狀態

關於pprof

必須要先安裝好Graphviz

  • 執行go tool pprof http://localhost:YOUR_WEB_PORT/debug/pprof/profile
  • (pprof) top10
  • (pprof) web

會出現一個圖類似以下:

image

###問題: Go-martini會將handler預設是沒有開放的,所以會得到404 page not found:

這邊有個討論串,我覺得Patrick這個解法挺好的.

 import "net/http/pprof"
 
 //Some martini init here.
 m.Group("/debug/pprof", func(r martini.Router) {
        r.Any("/", pprof.Index)
        r.Any("/cmdline", pprof.Cmdline)
        r.Any("/profile", pprof.Profile)
        r.Any("/symbol", pprof.Symbol)
        r.Any("/block", pprof.Handler("block").ServeHTTP)
        r.Any("/heap", pprof.Handler("heap").ServeHTTP)
        r.Any("/goroutine", pprof.Handler("goroutine").ServeHTTP)
        r.Any("/threadcreate", pprof.Handler("threadcreate").ServeHTTP)
    })

心得:

  • 使用gcvis可以幫助你瞭解目前Heap的數量,記憶體使用數量與GC發生的次數.記住,越多的GC代表著系統資源消耗在回收與釋放記憶體.
  • pprof可以完成一個樹狀圖.不過,目前在Web Application這裏可能還需要有更多的技巧找出真正卡住系統資源的地方.
  • Go 1.5 有出新的tracer, 等 1.5出來可以試著用用看….

相關文件:

[MOOCS][Golang]MIT6_824 Distributed Systems Week2(Lec2/Lab2A)

##前言:

本週進入第二個禮拜,開始有一些分散式系統的備份與替換的問題還有論文. 加油吧!!

MIT 6.824 分散式系統 系列文章

6.824: Distributed Systems

##第二週課程:

##關於筆記 Primary/Backup Replication (Remus)

盡量用理解後的中文紀錄,原始筆記在這裡:

  • 關於容錯(Fault Tolerance):
    • 希望能繼續服務儘管有問題發生. 特性如下:
      • 可見性: 即使有問題發生,也希望服務能夠繼續.
      • 正確性: 希望發生問題的時候,服務也跟單機一樣(無錯誤時)正確.
    • 核心想法: 備份,透過兩個或是以上的備份伺服器來預防任何的問題產生.
      • 重要問題:
        • 備份機的狀態?
        • 工作機的狀態如何轉移?
        • 何時要切開與備份機的連接?
        • 異常發生在切開之後?
        • 如何修復與重新連接備份機?
    • 兩個關於備份機的重要動作:
      • State Transfer (狀態轉移)
      • Replicated State Machine: (備份狀態機)

##論文 Remus: High Availability via Asynchronous Virtual Machine Replication

這裏有網頁版本

Remus 的系統特色:

  • 整個系統備份
  • 對於Application與Client而言是透明的.
  • 當運行成功的時候,備份與切換機器就運作順暢

image

圖片元素解釋:

  • Primary: 具有資料,會執行OS與App,並且負責跟Client溝通.
  • Backup: 只有資料,但是不執行OS與App.只有跑一些Remus的code

流程簡介:

  • (1) Primary 跑完 Completed Execution (E1),並且先不回傳E1結果回client.
  • (2) Primary把結果備份到Backup (背景執行)
  • (3) Backup同步所有目前資料跟Primary一樣.
  • (4) Primary 執行Speculative Exection (E2),並且先不回傳給client
  • (5) Backup 複製所有結果
  • (6) Primary放出E1結果
  • (7) Backup 把結果存入RAM/Disk.

Remus 特性與檢討:

Remus系統的估計

  • 速度為單機系統的1/2~1/4
  • Check point時間過久
  • 為了要能夠與client溝通,保留結果的時間不能太久

缺點

  • 速度不快:
    • 由於每個Exection都必須等待Backup 複製好相關資料。
    • Check point 至少等花上100ms

如何改善:

  • 減少主機儲存資料
  • 減少狀態的資料量,或是優化資料格式
  • 試著傳送指令而非狀態

##關於Lab2 Part A:ViewService

這一篇有點困難,所以稍微做點筆記:

###題目解釋: 主要要implement 一個具有faul-toerant的key/values services- Viewservice.這個Service有以下的幾個功能:

  • 監控 Primary (指的是原始service) 與 Backup(備份用的Service)是否是正常工作.
  • 正常而言,如果Primary壞了,會自動地把Backup promoted成 primary.此時如果有空的server就會拉近來變成新的Backup.
  • 當新的Primary與Backup上線後,Primary還有一個工作:
    • 備份所有資料庫給Backup
    • 所有的command set傳給Backup去確保Primary與Backup state machine是一致的.

關於ViewService的Primary/Backup轉移範例如下:

  • Primary (Server 1: S1) 發生問題,而Client 送給 S1 一個需求OP1.
  • Primary 轉發OP1 給 Backup(Server 2: S2), 這個動作是之前提到為了同步的關係.S1會把每個收到的指令透過forward轉給S2
  • 但是由於S2已經被promote成新的Primary.而這時尚未有新的Backup上線.
  • S2 回傳一個Error 給 S1 並且Forward給 Client 說已經沒有Backup Server.
  • ViewService會把S2設定成新的Primary target address 並且把新的指令都直接轉給 S2.

###開始解答:

打開viewsource這個資料夾,主要有幾個需要注意的:

  • server.go :主要code的部分.裡面主要有以下幾個部分需要思考:
    • Ping(): 主要負責的是接受Server的Ping,在其中包含著Server本身的資訊與現在資料的View number
    • Get(): 取得資料
    • Tick(): 這個也就是所謂的定期Heartbeat 也可以說經過一段時間會自動啟動的timer,如果有任何Server掛掉,必須要在這裡處理.
  • test_test.go:本次作業的測試程式,需要好好思考其中代表的涵意

####進階與Server有關的邏輯與含意

這邊可以參考它提供的圖片: image

在這裡也整理一下幾個需要注意的地方:

  • 其中Viewnum代表的涵意:
    • Viewnum代表Server所直接到的一個state或是第幾個View.他應該是一個會慢慢增加的部分.
  • 如何判定Server已經掛了:
    • Viewnum忽然變成0,如果原先的 viewnum已經>0,但是在某些狀況下忽然收到viewnum=0.那麼就是代表Server已經掛掉又重新執行.
    • 每一次Server的Ping,需要紀錄當時的時間.然後在tick裡面去檢查 DeadPings * PingInterval來確認Server是否掛了,但是某些狀況下可以當作是Server 繼續活著 (請看Ack).
  • 當Server掛掉的處理流程:
    • 如果是Primary掛掉,檢查是否有Backup.如果Backup已經正常在運作了,就把他切換成Primary. 並且把第三台主機當作Backup.
    • 如果是Backup掛掉,一樣會檢查是否有第三台主機,並且把它掛起來.
  • 回應(acknowledgement):
    • 在這裏一次的Get()Ping()被視為是一次的回應.並且注意Ping()viewnum必須要大於0,才能表示他已經開始運作.
    • 如果Primary主機有做Get(),但是卻沒有回應Ping(),在這次的處理必須等待而不能直接把主機關閉.(倒數第二個測試)
  • 伺服器初始化(Initialization):
    • 身為Backup主機,我們必須要確認Backup已經上線了(Online),唯一的方式就是確保他已經有Ping()一個數值超過0的viewnum
    • 如果Backup沒有初始化,是不能夠當作Primary的(最後的測試)

####心得與改進:

透過這些test case來開始這部分的作業,其實相當的有趣.一開始最令人困擾的是三個function不知道要拿來做什麼.其實題目不算是相當的清楚來解釋每一個步驟. 只能不斷地透過go test一步步來瞭解到底每一個流程,每一個原則會是什麼.這邊算是比較有趣也比較好玩的部分.

此外,由於流程裡要代表的狀態相當的多.一下子要確認主機是否有ack,一下又要確認有沒有init.簡單的做法可以透過許多個flag來代表個別的狀態. 當然,也可以使用狀態機(state machine)的方式方式來開發這次的作業. 只是要有可能會打掉重練的打算.

幾種重練的做法:

寫完作業後,對於論文Remus: High Availability via Asynchronous Virtual Machine Replication也比較容易了解了.

##參考文章: