乙個專案在初期的時候,為了盡可能快地驗證市場,其對業務系統的最大要求是快速實現。在這個階段,**開發人員為了能快速實現業務系統,一般都是將所有層級(mvc)的業務**都寫在同乙個專案中,所有的業務資料都存放在同乙個資料庫中。此時,專案的整體架構圖如下所示:
從上圖可以看到,我們在乙個專案中集中了註冊、登陸、購物三個模組的業務**,並且這三個業務模組都讀取同乙個業務資料庫。
但隨著專案的不斷推進,使用者量不斷增長,單台應用伺服器已經無法承受如此巨大的流量了。此時常見的做法是把專案進行分布式部署,分散單台伺服器的流量,從而可以暫時緩解使用者增長帶來的應用伺服器壓力。此時的專案架構圖如下所示:
但隨著我們部署的應用伺服器越來越多,後端的單台資料庫伺服器已經無法承受如此巨大的流量了。為了盡快緩解使用者訪問壓力,我們一般是在應用伺服器與資料庫伺服器中間加多乙個快取層,通過快取可以抵消掉一部分的資料庫查詢操作。此時的專案架構圖如下所示:
但是增加資料庫快取層只能緩解資料庫訪問壓力,攔截部分資料庫訪問請求。隨著使用者訪問量的進一步增長,資料庫訪問的瓶頸還是會進一步凸顯。這個時候,我們不得不對資料層的架構進行改造。
這個時候常用的解決方案就是將原本單台資料庫伺服器變成主從模式的資料庫伺服器,即一台資料庫作為主庫支援寫入資料,一台資料庫作為讀庫支援查詢資料。此時專案的架構圖如下所示:
我們通過資料庫主從同步實現了讀寫分離,將所有讀操作都引導到從庫進行,將所有寫操作都引導到主庫進行。
因為我們對資料庫層進行了改造,規定所有讀資料庫操作要訪問從庫,所有寫資料庫操作要訪問主庫,那麼我們就必須對原來的**進行改造。
public user selectuser()
public user insertuser()
上面是改造前的**,無論是讀操作還是寫操作,我們都使用同乙個資料來源進行操作。但為了適應新的資料庫架構,我們必須在**中手動判斷應該請求哪個資料來源。
public user selectuser()
public user insertuser()
經過修改後的**,開發根據自身經驗判斷應該選擇哪個資料來源進行操作。當是讀操作的時候,我們選擇 readtemplate。當是寫操作的時候,我們選擇 writetemplate。
但作為乙個程式設計師,我們隱隱約約覺得識別應該用哪個資料來源這個判斷不應該人工判斷,而應該自動讓**去判斷。畢竟這個判斷的模式很簡單 —— 如果是 select 那麼就用讀的資料來源,如果是其他那麼就用寫的資料來源。
其實這個就是 mycat 的用途之一,即作為乙個資料庫中介軟體去解決資料來源判斷問題。如果我們使用 mycat 作為資料庫中介軟體,那麼我們不需要關心我應該使用哪個資料來源。mycat 幫我們遮蔽了不同資料來源的差異,對於我們來說就只有乙個資料來源,這個資料來源能處理寫操作,也能處理讀操作。上面查詢和插入的**就可以變成下面這樣:
public user selectuser()
public user insertuser()
實現了主從資料庫架構,再使用 mycat,你發現我們並不需要去修改太多的**,只需要將資料來源改為 mycat 位址即可。mycat 自動把我們所有的語句傳送給後端的 mysql 伺服器。
上面說的這些問題只是實戰中遇到的一部分問題,事實上遇到的問題只會更多不會更少,而且隨著業務的不斷發展會愈加凸顯。
此時為了各個業務模組不互相影響,我們把應用層進行垂直拆分,即把註冊模組、登陸模組、購物模組都單獨作為乙個應用系統,分別讀寫獨立的資料庫伺服器。此時,我們的系統架構圖如下圖所示:
實現了垂直拆分之後,我們可以成功解決上面說到的三個問題:業務模組相互影響問題、單資料庫壓力問題。
但是隨著業務的進一步擴大,我們又增加了許多業務模組:客服模組、錢包模組、個人中心模組、收藏夾模組、訂單模組等。按照我們之前所設計的資料庫架構,我們會存在許多個資料來源,這些資料來源分散在各個專案中:
對於乙個專案管理者來說,這麼多的資料來源分散在不同專案中,怎麼統一管理是乙個問題。很多時候我們都很難記住這個專案連線的是哪個資料庫,那個專案連線的是哪個資料庫。
但如果你使用了 mycat 作為資料庫中介軟體的話,mycat 就可以幫你解決這個問題。對於所有專案來說,它們只需要統一連線 mycat 對外提供的乙個位址,而 mycat 則幫這些專案聯絡所有後端的 mysql 資料庫。對於前端的專案倆說,它們只知道 mycat 這個資料庫中介軟體,而不需要去理會我到底連線哪個資料庫,mycat 通過自身配置可以完成這個任務。
當資料庫架構經歷了主從架構、垂直拆分架構之後,應對一般的業務讀寫是沒有什麼問題了。但對於一些核心的業務資料,可能還是會有瓶頸問題,例如使用者模組。
對於一些使用者量高達乙個億的使用者系統來說,即使經過主從架構、垂直拆分架構的優化,但其使用者資料庫的單個表裡需要儲存的資料還是高達乙個億的大小。如果我們把所有的資料都存放在乙個表裡,無論是註冊時的插入資料,或者是登陸時的查詢資料,勢必會變得很慢。
這時候,我們就不得不對這些高資料量的核心業務表進行水平拆分,即將海量的資料記錄拆分到多張表中儲存。例如我們一開始可能只有一張 user 表,我們將 user 表按照使用者 id 對 1000 取餘進行拆分,那麼我們就會有 1000 張表,分別是 user_000 至 user_999。此時,專案的架構圖如下所示:
當我們在**中查詢使用者資料時,我們先根據使用者 id 取餘判斷其應該操作的表,之後再查詢對應的表。例如 userid 為 90749738 的使用者就應該查詢 user_38 表,userid 為 74847383 的使用者就應該查詢 user_83 表。
通過水平拆分,我們成功解決了海量資料核心業務表的讀寫瓶頸問題。但此時在**層面上有乙個問題出現了,那就是我們需要在查詢資料庫之前,根據 userid 去判斷應該查詢哪個表,這個操作對於所有業務模組來說都是高度一致的,應該抽離成乙個公用的專案。
與判斷應該使用讀資料來源還是寫資料來源一致,我們都覺得這樣機械的任務不應該丟給程式設計師做,應該讓機器去做。這其實就是 mycat 可以幫我們做的事情:mycat 通過配置一系列的分庫分表規則,讓 mycat 幫我們自動判斷應該查詢哪乙個分表。通過使用 mycat 資料庫中介軟體,我們可以省去在**層判斷查詢哪個表的冗餘**,從而讓開發人員更專注於業務邏輯的開發。
從單一的資料庫架構,到主從讀寫分離的資料庫架構,再到垂直拆分、水平拆分的資料庫架構。我們可以看到 mycat 幫我們解決了讀寫資料來源判斷、繁雜資料源位址、分表判斷這三個機械的重複性的問題。
上面說到的三個功能就是 mycat 誕生初期的最基本功能。但 mycat 發展至今,其功能已經遠遠超過上面說的這三個。例如 mycat 支援主從切換功能,當資料庫主庫發生網路問題或其他故障時,mycat 可以自動切換到從庫,從而保證正常讀寫功能的進行。
總的來說,mycat 的定位是乙個資料庫中介軟體。但凡所有處於應用層和資料層之間的事情,mycat 都可以做。
MyCat 啟蒙 分布式系統的資料庫架構演變
public user selectuser public user insertuser public user selectuser public user insertuser public user selectuser public user insertuser 即使每次改動的 即使很小...
分布式 分布式系統的設計
在計算機領域,當單機效能達到瓶頸時,一般有兩種方式解決效能問題 而分布式系統的設計說白了就是 如何合理將乙個系統拆分成多個子系統部署到不同機器上。講設計方法前,先介紹分布式系統的特性 1 分布性 空間中隨機分布。這些計算機可以分布在不同的機房,不同的城市,甚至不同的國家。2 對等性 分布式系統中的計...
分布式系統 資料分布方式
分布式系統如何拆解輸入資料,將資料分發到不同的機器中。下面將介紹幾種不同的資料分布方式。color red b 一 雜湊方式 b color 雜湊方式是最常見的資料分布方式,其方法是按照資料的某一特徵計算雜湊值,並將雜湊值與機器中的機器建立對映關係,從而將不同雜湊值的資料分布到不同的機器上。所謂資料...