最近看了很多公司架構的演變的文章,發現其中的基本思路和架構演變都很類似,這里也總結一下數據庫架構的演變以及演變背后的思路。
單主機
最開始網站一般都是由典型的LAMP架構演變而來的,一般都是一台linux主機,一台apache服務器,php執行環境以及mysql服務器,一般情況下,這些都在一台虛擬主機上,簡稱單主機模式。
單主機模式缺點:
1 web服務器和mysql服務器公用一台主機,共享硬件資源,可能存在某一方資源征用太大,導致整個應用產生瓶頸
2 當業務增長之后,沒有辦法做到橫向擴展。
3 容錯性太差,一旦主機存在問題,整個應用不可用
獨立主機
隨着業務的發展,可以把mysql服務器和web服務器主機分開,分別部署,就是獨立主機模式。
獨立主機模式下,web服務器和mysql不再共享硬件資源,分別部署。沒有把雞蛋放在一個籃子里面,增加了容錯性。如果只是mysql服務器故障,那么對於web上不訪問服務器的應用是不會受到影響的。而且web服務器可以做到橫向擴展,如果web服務器性能不夠,可以增加多台web服務器,進行負載均衡,分散web服務器的壓力。
獨立主機模式的缺點:
1 可擴展性問題:雖然web服務器可以做到橫向擴展,但是mysql服務器是沒有辦法做到橫向擴展的。
2 可用性問題:mysql服務器存在單點問題,一旦mysql服務器宕機,對影響的影響很大
3 性能問題:單台mysql服務器能夠支撐的服務是有限的。
讀寫分離
隨着業務的不斷發展,數據庫的壓力會越來越大,單數據庫慢慢的就不能滿足需求了,一些網站對數據實時性要求不高,就會慢慢發展讀寫分離模式,對於普通的查詢請求,分配到讀庫(也可以說是備庫),對於修改請求,在主庫上完成。對於讀庫,由於是無狀態的,可以做到橫向擴展。對於寫庫,還只能是單台主機
這種模式其實有限制的,要根據業務的類型來考慮。主庫的數據是最新的,但是同步到讀庫會有時延,所以應用必須能夠容忍短暫的不一致性。對於一致性要求非常高的場景是不適合的。
這種模式的存在的問題:
1 可擴展性:雖然讀庫可以做到橫向擴展,但是寫庫還不行,讀庫不能夠橫向擴展
2 可用性:讀庫成為單點,一旦故障,影響所有的寫操作業務
業務垂直拆分
隨着業務的發展,一台寫庫顯然不能夠滿足高並發的情況,但是考慮到寫庫是有狀態的,不能簡單的橫向擴展,假設有兩台寫庫,那么隨機更新一台的數據,就會導致另一方數據存在問題。出現一種數據兩個不同版本,顯然是無法接受的。在寫庫上,可以考慮按照業務來垂直進行分庫。由於我們這里討論的是數據庫架構,對於web層來說,其實也是可以按照業務垂直拆分的。
在按照業務垂直拆分以后,系統在性能上有了很高的提升,只需要把業務上分成垂直部分,分的越細,系統的整體擴展能力就越強。
這種模式下,存在以下幾個問題
1 可用性:假設一個完整的業務流程P訪問的數據庫被拆分為A、B、C、D、E 五個庫,假設每個寫庫可用性為99%,那么這個業務流程P的可用性就為99%*99%*99%*99%*99%=95%,庫拆分的越多,對系統的整體可用性挑戰就越大。
2 性能:由於垂直業務庫每個庫的負載可能不一樣,假設交易庫負載很高,一個交易寫庫肯定不能夠滿足需求,這個情況下,交易庫成為整個系統的瓶頸。
3 可擴展性:單個節點的可擴展性沒有得到改善,交易庫不能單獨進行擴展。
單業務庫水平、垂直拆分
在上一種情況,假設交易庫是整個系統的瓶頸,需要對交易庫進行單獨的擴展。可以考慮交易的水平拆分或者垂直拆分,有可能同時進行兩種方式拆分。
水平拆分一般根據業務無關的關鍵字進行拆分,橫向擴展性比較好,但是對於查詢的挑戰比較大
垂直拆分一般根據業務來拆分,但是可能導致數據不均勻以及拆分不夠靈活。對於查詢來說,相對比較友好
拿交易庫舉個例子,可以先交易的類型進行業務上的垂直分庫,在按照訂單號進行水平分庫。
假設可以分成M*N個庫,那么單個庫的故障會影響1/M*N 的交易,但是假設每個庫可用性為99% ,那么交易數據庫故障概率為 (99%)的(M+N)次方,如果數據庫拆分的越多,發生單個數據庫故障概率就越高。
這種方式存在的問題:
1 雖然單個節點故障影響的用戶很少,但是整體可用會降低。
2 數據庫管理上帶來復雜的挑戰,假設交易庫表結構變更,需要執行M×N次腳本變更。
3 由於發生單個數據庫故障的概率比較高,dba會很苦逼的,估計經常性要救火
4 開發和測試起來會非常苦逼,開發和測試成本會變高,查詢非常復雜。
5 單個節點如果發生故障,沒有失敗檢測並且切換機制
6 分庫還不能在水平方向做到無限擴展,我們的算法是事先分配M個庫,如果添加一個庫基本上不可行
隨機分庫
對於第六個問題,在水平方向的無線擴展,可以考慮一種機制,在insert數據的時候,申請一個數據庫編號,然后把數據庫的編號作為一個字段保存或者在把這個編號添加到已經字段上。
例如假設我們申請insert數據庫,得到一個數據庫編號為1000,那么我們可以構造出來一個訂單號為1000_tradeno,訂單號前面是分庫編號,訂單號后面是實際tradeno,這樣解決了水平無線擴展的問題。這種就是隨機分庫模式。但是這一種方式的局限性很大,
隨機分庫的缺點:
1 分庫算法和業務耦合在一起,比較適合特定的場景,適用范圍比較窄
2 對於insert操作,比較容易,對於update操作,必須有分庫編號,也就是說,只能根據特定的字段來進行更新
3 不適合批量查詢的場景,查詢功能限制比較大,這也是分庫帶來的問題
單數據庫備份以及失敗切換
對於單個數據庫,如果發生故障,會影響業務,但是能否在發生故障的時候進行切換。雖然可以實現,但是會存在一定的問題,需要特定場景進行特定的分析。這一塊比較復雜,說起來可以在寫一篇文章,就簡單的介紹一下
以上就是總結的數據庫的架構演變,數據庫的演變需要很多基礎技術做支撐,主要包括
1 強大的分布式數據庫的管理中間件,主要屏蔽底層的數據庫路由以及數據管理功能
2 強大的數據運維團隊以及監控體系,能夠檢測出每個節點的數據庫狀態
3 強大的數據庫管理管理團隊,能夠維護這么的數據庫集群
4 強大的業務架構能力和技術架構能力,能夠掌控這么復雜的業務場景。