在前文中我們談到所謂的「規模可擴充性(scalability)」,一個系統有沒有規模可擴充性,我們看的並不是單一計算節點上跑多快,而是當你增加計算資源(例如機器、頻寬)時,能否透過增加計算資源,來換取更大規模的處理能力。

當在解決大型規模的計算問題時,人們關心能否透過增加伺服器、頻寬、儲存空間的方法,來服務更大規模的用量,更勝於在單一伺服器上可以執行多快。

要得到規模可擴充性,並不是一件容易的事情,但如果可以從平臺本身獲得支援,包括計算能力及資料存取等,對應用程式來說,會簡單許多。而這也正是一些所謂「雲端計算平臺」的作用所在。

另一方面,我們談到了「雲端計算平臺」,並不是建構在「雲端計算平臺」上的應用程式,就必然具備規模可擴充性。

例如,對於應用程式來說,它有可能是建構在 IaaS(Infrastructure as a Service)的層次之上,或者,也可能是在PaaS(Platform as a Service)層次上所發展的。

通常,建立在IaaS 上的應用程式,無法直接得到規模可擴充性,平臺通常可以提供的部分,只是「依用量可隨時動態彈性配置的資源」。就像在 AWS 的 EC2 上運行應用程式,並不能保證應用程式的規模可擴充性,充其量,只能在你需要伺服器、頻寬、儲存空間時,EC2 能夠盡可能地動態滿足你的需要。

所以說,並不是把應用程式搬上了「雲端」,就必然獲得了規模可擴充性,當你只是在 IaaS 平臺上開發時,是否具備規模可擴充性,仍舊取決於你的系統架構及特性。

不過,當你是在 PaaS 上開發時,情況又有所不同。PaaS 平臺本身,會處理掉許多和規模可擴充性相關的問題,就像是在 Google 的 App Engine 上面,它所提供的資料存取操作,就不同於傳統的關聯式資料庫,而是以 BigTable 為基礎的操作模式,這使得它有能力處理海量資料的存取。而立足在 App Engine 之上的應用程式,自然而然,具備著更好的規模可擴充性。

因此,在一個專門為了更大規模而設計的平臺上開發,對於想要得到規模可擴充性的應用程式開發者來說,可以省去不少的力氣。其中像 Hadoop 便是一個為了大規模計算而設計出來的平臺,其中,利用所謂MapReduce的計算方式,可以將計算量分散到各個能提供計算的機器之上,集合眾多機器之力,因而在更短的時間內,解決想要解決的計算問題。而且,可以彈性投入所能配置的資源數量,投入的愈多,解決的愈快。例如,動用更多的伺服器,就能更快的解決計算問題。倘若預算不那麼充分,也可以使用較少的機器,但耗費較多的時間,而這正是規模可擴充性的意義所在。

分散式計算的迷思

雖然說,分散式計算的目的之一,就是希望透過將計算量分散到多部、不同的機器上,來增加整體的計算能力,但是,並不是所有的應用程式都可以輕易拆散到多部機器之上去運行,而且更重要的是,並不是將應用程式拆分到多部機器之上,就必然帶來整體計算量的提升。

舉例來說,倘若你將你的應用程式拆成多份,並且同時傳輸至多部機器之上執行,而這幾個程式之間需要溝通,也就是交換資料,它們之間甚至需要做同步(synchronization),以致於不同機器上的程式之間需要等待特定工作的完成,接著才能繼續執行,那麼,這樣的應用程式就不見得具有規模可擴充性,因為,等待的環節,會造成規模無法隨著計算資源投入而跟著成長的因素。

這說明了,即使試著將計算拆分成為多份,並且置於多部機器上執行,也不見得可以獲得多倍的效能改進,很可能因為計算模式的特性所限,而僅能獲得少數的效能成長,而且隨著規模愈大,成長的比例愈低。因此,如何拆分計算工作,使得它們被散布到多部不同的機器後,可以得到對應的計算規模提升,就成了這件事情的核心議題。

透過分而治之的方式,將大問題拆開許多個小問題,個個擊破,降低解決問題的難度

像 Hadoop 的 MapReduce,就是一種拆分計算工作的方式。想要透過拆分工作來解決計算問題,傳統的「分而治之(Divide and Conquer)」其實,就是一種可行的方式。所謂的「分而治之」,就是將一個大問題,拆解成多個小問題,而分別解決這些小問題的答案之後,再將這些答案透過某種方式合併起來,就可以得到大問題的答案。這種方式常常可以遞迴為之,也就是拆成比較小的問題之後,還可以接著再繼續拆解,直到拆解至適合解決問題的規模為止。

如果,我們可以運用「分而治之」的方式來解決問題,就很容易得到規模可擴充性,因為,我們可以將原始的問題拆解成若干個較小規模的問題,然後把這些問題分別置放在不同的機器上解決,因為解決這些小問題的計算是互相獨立的、它們之間也不需要溝通,所以,當可運用的機器數量變多時,就可以將問題的規模拆解的更小,使得在單一機器上解決它們的速度更快,更使得整體解決它們的時間可以縮短。而 MapReduce 正是此種「分而治之」的解題計算模式,當你運用 MapReduce 時,便得以此種方式來思考解決問題的方法。

函數式程式設計開始流行

在另一方面來看,你可能也會發現到,所謂「函數式(functional)」的程式設計方式,在這種「分而治之」的分散式計算模式裡,開始受歡迎了起來。函數式的程式語言已經有幾十年的歷史,早期像 Lisp 的程式語言,主要是應用在人工智慧的領域。但是,為什麼在這個應用領域裡,反而流行起來了?

函數式的程式語言有一些特性,包括程式中是沒有狀態(stateless),而且每次函式之值被評估(或說被執行)時,是沒有副作用的(side effect )。

所謂的副作用,代表的是函式被執行時,除了它主要應該達成的作用之外,還有一些其他附屬的效果,此即其副作用。主要的作用,就像是函式的回傳值,而副作用,則像是除了回傳函式之值以外,還同時改變全域變數的值。你可以想像,函式的回傳值,除了被其輸入參數所影響之外,還同時被其他的狀態,像是全域變數所影響時,會產生許多意想不到的結果。

但是如果我們從數學上的函數的角度來看,f(x) 之值,完全取決於 x ,沒任何 f() 內部的狀態或是外部的狀態足以在 x 相同時,造成 f(x) 之值不同。而所謂的函數式程式設計方式,便是在特性上有著此種取向,因此,它沒有狀態、也沒有副作用。

這種特性之所以能對分散式計算帶來好處,我想是因為在有這樣的特性之後,計算工作會更容易分配到不同的機器上去計算。正如數學的函數一樣,只要給定相同的輸入值,就一定會算出相同的輸出值。計算工作之間的相依性降低了,不論在那部機器上算、在什麼時間點算,都不會影響到計算的結果。因此,當以「分而治之」的原則來拆解計算工作,以進行分散式的計算時,更容易拆解工作、更容易合成計算結果,以成為最後的結果。

透過一個更高階的雲端計算平臺,以及計算模式,其實,可以讓程式設計者更容易的取得規模可擴充性。而從現在的趨勢來看,函數式的設計方式,應該還會再流行好一陣子。

專欄作者

熱門新聞

Advertisement