摘要
商業服務的PostgreSQL Database Cluster![]() (本文圖片皆引用自PGCluster官方網站,http://pgcluster.projects.postgresql.org) 我在商業服務的Ruby on Rails HTTP Cluster觀念及測試中的第一張圖的前面那一段有提到說,DB的情況有點像是如此,不過實際上情況有點不同。因為有網友的疑問,如今我認為該是時候補完一下。 應用系統如果要能夠真正地服務大量的使用者,與常見裝個MySQL然後跑個PHP論壇程式,是完全的兩回事。因此一個良好的資料庫管理員, 必須清楚地知道自己的應用程式與資料庫在單台機器上執行的時候,效能的瓶頸在哪裡。如果不清楚應用程式及資料庫各佔的資源比例,那在切割成叢集的時候,並 不見得有顯著的效能提升,因為負載平衡以及複寫管理的程式都會吃CPU。認為1+1就極有可能等於2,這個是一般的管理員錯誤的認知。 舉例來說,許多大型的論壇,擁有上萬使用者,每天流量破10G;這樣的論壇,有些時候一開始因為資金及管理人力的限制,會考慮只買一台效能 相當好的伺服器(例如HP ProLiant 380 G5),並且將Apache+PHP(應用程式)與MySQL(DBMS)擺在同一台主機上。管理員會想說反正這台效能高,一方面省下買另一台伺服器的 錢,一方面PHP程式不用透過網路與MySQL連線,理論上應該效能很好。卻沒有考慮到,一般的論壇Web應用程式是以CPU及RAM需要量大的應用,而 DBMS是一種I/O裝置(RAM+Disk)需要量大的應用。這是由於,大多數的管理員會誤以為DBMS僅吃CPU與RAM。負載低的時候看起來沒什 麼,一旦人數增多,表示應用程式的部分記憶體就會越吃越多。系統用來快取的記憶體不足,很快地瓶頸就會出現在記憶體及硬碟之間,造成資料庫效能低落。這個 代價比使用兩台機器跨網路線這樣的部署方式要來的大太多。 叢集化在DBMS相關議題中,有幾個主題會在叢集化的時候一起討論。 複寫管理(Replication Management)複寫可以理解為「複製」的意思,不過複寫這個詞更強調的是資料的一致性。在DBMS中進行的複寫,是針對Insert,Update,Delete 三個指令,將指令在所有的節點上執行,並且必須檢查這些動作後資料是否一致。目前所有開放原碼的PostgreSQL專案中,比較有名的是 PGCluster,PGPool及Slony-I。 PGCutser是一種多服務點(Multi Master)的複寫系統,意指資料會在節點之間全部同步,儘管會有些許時間延遲,但不至於有影響。與Master-Slave不同,並不需要寫入特定某 個節點才能複寫至其他節點。PGPool也有相似的作法,也同時允許對多個節點進行複寫,但實做方式可能不同。 (註:儘管PGCluster與PGPool在技術上相似,但有些文章並不認同它們兩個是使用類似的技術) Slony是一種Msater-Slave的複寫系統,資料只能夠從指定的節點寫入,而複寫至次要節點的時間也會稍微延遲。 複寫儘管能夠在資料庫叢集上發揮作用,也能夠做為備份使用。總之資料庫同步了,就看你要拿去做什麼用途。此外同步的複寫,與延遲的複寫,所影響的也只是被複寫的資料庫是否是要做線上使用。如果是延遲複寫,就要注意最好是當作備份,而非拿來做線上使用。 Statement Level 與 Row Level ReplicationStatement Level與Row Level意義上就是,前者是複製SQL指令,後者是複製執行完SQL的一筆記錄。上述所有三套複寫管理的程式,都是採用Statement based。而像MySQL, Oracle等都有提供Row based replication。這兩種複寫的差異在於,一旦你的statement是Procedural Language,有可能在不同的節點上會造成不同的結果(non-deterministic),那複寫便失敗了。而Row based的好處正是反過來,既然已經知道結果,便不會有任何差異的可能性。 查詢緩衝(Query Pooling) 對於許多應用程式而言,很有可能連續地進行同樣的查詢。例如你將應用程式的功能選項名稱列舉在表格裡,那為了讀取所有選項,都會進行同樣的 查詢。這樣的查詢與結果,是不需要再傳回實體資料庫真正進行查詢的,因此就由緩衝區直接將結果傳回。以資料傳輸的角度來說,在Client使用的函式庫裡 實做緩衝,就不用再進行網路傳輸,比在Server上實做有意義多。 不過PGPool就是這樣的一套軟體,他也採用了查詢緩衝機制,使得同樣的查詢不會重複地傳給後端的實體資料庫。 負載平衡(Load Balance)如同字面意思,當有大量連線進入的時候,負載平衡程式要能夠得知所有連線中的資料庫,並且將查詢分散給這些資料庫查詢。當有任何資料庫中斷,負載平衡程式也不能夠傳給已斷線的實體資料庫,以免造成應用程式錯誤。PGCluster與PGPool都有負載平衡能力。 另一種獨特的負載平衡,是將一個資料表格切割,散佈在所有的實體資料庫內。這種不僅做到了負載平衡,更有可能實現平行查詢。PGPool擁有切割表格並且平行查詢的能力。 共享儲存系統(Shared Storage System)與磁碟鎖定管理員(Disk Lock Manager)如果你的資料庫儲存系統效能相當地好,或許你可以考慮使用共享儲存系統來讓一份資料庫的資料檔,能被多個資料庫系統實體同時讀取。在這種情況之下, 當然你就不需要複寫系統來讓資料庫同步了。不過這也延伸一個問題,畢竟多個城市實體要進行寫入的時候,那就可能造成衝突,也因此使用何種磁碟鎖定管理員就 有很大的差別。Oracle附了自行開發的鎖定管理員,而其他的開放原碼資料庫就得尋找其他開放原碼的解決方案。 儘管有些檔案系統具有共享的特性(如NFS),但卻並非相當適合當作資料庫存取的機制使用。另一個著名的檔案系統Global File System(GFS)已經被證實能與PostgreSQL一起運行,GFS本身也帶有DLM。 有網友詢問說資料庫能否建置在這樣的共享儲存系統上?在這裡要說明,即便你有高出力的儲存硬體,但你還是得想清楚,共享檔案系統就是靠網路進行I/O,資料庫是一種依賴I/O的應用程式。如果你只有100Mbps的區域網路,還是打消念頭吧! SQLServer的部署這裡要提到部署的作法,是適用在全部的DBMS上。使用不同的部署方法,會影響到建置及維護複雜度,效能,可擴充性。 單服務點(Single Master)單服務點所要顧慮到的只是上述所說的,「除非真的窒礙難行,不然別輕易地把應用程式與DBMS擺在同一台主機上」。一般來說你的應用程式應該是能完
全與單服務點的資料庫一起運作,對於你的應用程式而言,他與一個單機的資料庫沒有啥兩樣。所以,不管你用PGPool或是PGCluster,應該會預設
設定為單服務點。如圖: ![]() 這樣建置的優點還是較為簡單,但這個作法的極限就在於一旦你發現你的負載平衡程式已經消耗過多的CPU,或是對應用程式的頻寬已經大到明顯拖慢速度,就是該換架構的時候了。 多服務點(Multi Master)多服務點就相對地複雜,如果你會採用多服務點,一定是因為你的應用程式服務點也相當地多。例如說你的應用程式伺服器有上百個,但怎麼可能上百個都向同一個(單服務點的)負載平衡程式進行連線?不管你用多快的CPU,給多大的記憶體,都一樣會爆掉。 這個時候你也不可能考慮單一的儲存系統,所以你只剩下一個選擇就是進行複寫,並且實做多服務點架構。 參考http://wiki.postgresql.org/wiki/Replication,_Clustering,_and_Connection_Pooling http://www.openminds.co.uk/post_gre_sql_mirroring_and_recovery.aspx http://www.postgresql.org/docs/8.3/interactive/high-availability.html http://www.openminds.co.uk/post_gre_sql_mirroring_and_recovery.aspx |