數(shù)據(jù)庫讀寫分離是很多公司繞不過去的一個發(fā)展階段赡若,從單體數(shù)據(jù)庫达布,到主備模式,再到讀寫分離逾冬,分庫分表黍聂。每一個階段都能為我們解決一些問題,但也帶來了新的挑戰(zhàn)。本篇文章我們就主要研究一下數(shù)據(jù)庫讀寫分離及其帶來的問題如何解決分冈。
1 數(shù)據(jù)庫架構的發(fā)展歷程
首先簡單介紹一下數(shù)據(jù)庫架構的發(fā)展歷程圾另,基本就是單體霸株、主備雕沉、讀寫分離、分庫分表去件,下面我們分別進行介紹坡椒。
1.1 單體架構
業(yè)務發(fā)展初期,數(shù)據(jù)庫的壓力相對較小尤溜,這時候使用單獨一個庫就可以倔叼。
引出的問題:如果數(shù)據(jù)庫出現(xiàn)故障,我們的業(yè)務就不能使用宫莱,只能說是停機重啟修復故障丈攒。
1.2 主備架構
由于單體帶出的問題,這時候我們就需要加一個備用庫授霸,緊急情況可以用備庫頂上巡验,相當于加一個替補隊員。
通過MySQL自帶的主從同步機制,就可以放我們的替補隊員上線。
當正式隊員(主庫)發(fā)生故障钩乍,我們就可以人工讓其下線胡桃,讓替補隊員(備庫)頂上。
引出的問題:隨著業(yè)務大規(guī)模爆發(fā)蚀之,主庫的壓力過大,我們就想讓備庫承擔起更大的責任來。
1.3 讀寫分離架構
讀寫分離架構本質(zhì)也就是主備架構指攒,與主備架構沒有本質(zhì)區(qū)別,就是在主備架構的基礎上僻焚,增加一層對讀寫請求的處理允悦,使其能夠更大程度上利用備用庫為我們分擔一些讀的壓力。
讀寫分離架構溅呢,需要在中間加一層控制讀寫請求的路由
1.4 分庫分表
分庫分表的本質(zhì)上是切分數(shù)據(jù)澡屡,是由于數(shù)據(jù)量級的提升,不對數(shù)據(jù)切分會嚴重影響數(shù)據(jù)庫讀寫性能咐旧。
甚至是如果不切分驶鹉,磁盤、內(nèi)存铣墨、CPU無法承載這樣的壓力室埋,數(shù)據(jù)庫隨時在奔潰的邊緣。
分庫分表與前三者是有本質(zhì)區(qū)別的,分庫分表后每一個庫分片都可以采取以上三種方式的任意一種姚淆,可以是單體分片孕蝉,也可以是主備分片,也可以是做了讀寫分離的分片腌逢。
分庫分表和前三者中的一種是共生的關系降淮。
不知道如何進行分庫分表設計的可以讀我之前的這篇文章《收好這份武林秘籍,讓你分庫分表再無煩惱》
2 讀寫分離設計方案
主從復制是MySQL數(shù)據(jù)庫自帶的功能搏讶,但是想要做讀寫分離就需要我們自己做一些工作配合MySQL主從同步配合使用佳鳖。可選擇的方案有很多媒惕。
2.1 代理
在應用程序和數(shù)據(jù)庫之間增加代理層系吩,代理層接收應用程序?qū)?shù)據(jù)庫的請求,根據(jù)不同請求類型轉(zhuǎn)發(fā)到不同的實例妒蔚,實現(xiàn)讀寫分離的同時還可以實現(xiàn)負載均衡(讀請求按照負載均衡的規(guī)則傳入各個從節(jié)點)穿挨。
代理也就是借助中間件的方式,控制不同類型請求肴盏,進入不同的數(shù)據(jù)庫科盛。
目前常用的mysql的讀寫分離中間件有:
- MySQL-Proxy MySQL自己的一個開源項目,通過其自帶的Lua腳本進行SQL判斷
- Atlas Qihoo 360,在mysql-proxy 0.8.2版本的基礎上叁鉴,對其進行了優(yōu)化土涝,增加了一些新的功能特性。
- MyCat
- MaxScale MariaDB 開發(fā)
- Amoeba 阿里開發(fā)
- ...
2.2 應用內(nèi)路由
在程序中進行控制幌墓,我們利用持久層框架的攔截器實現(xiàn)但壮,動態(tài)路由不同數(shù)據(jù)源。
利用Sharding-JDBC也可以實現(xiàn)
實現(xiàn)思路:
- 配置多數(shù)據(jù)源
- 設置默認的數(shù)據(jù)源常侣,配置數(shù)據(jù)源的切換策略
- 攔截進入數(shù)據(jù)庫的請求蜡饵,根據(jù)業(yè)務需求設置走哪個數(shù)據(jù)源。
3 讀寫分離造成的讀延遲怎么辦胳施?
凡是采用讀寫分離架構溯祸,就會有同步延遲問題,我們只能想辦法去克服這個問題舞肆。
3.1 數(shù)據(jù)同步寫入從庫
主從復制模式焦辅,一般都是異步寫數(shù)據(jù)到從庫,當然這個異步也可以設置為同步椿胯,只有當從庫寫完成筷登,主庫上的寫請求才能返回。
這種方案是最佳單也是最有效的一種哩盲,但也是性能最差的一種前方,尤其是有大量從庫的情況下狈醉,嚴重影響請求效率。
3.2 緩存(中間件)路由法
寫請求時緩存記錄一個key惠险,這個key的失效時間設置為主從同步的延時苗傅,讀請求的時候先去緩存中確認是否存在key,如果key存在說明發(fā)生了寫請求班巩,數(shù)據(jù)未同步到從庫渣慕,這時走主庫即可,若不存在這個key趣竣,直接走從庫的查詢即可摇庙。
中間件應該也是可以判斷是否同步完成旱物,與使用緩存記錄類似遥缕。
這種方案最大的弊端是引入了緩存,系統(tǒng)復雜度上升宵呛。
3.3 選擇性強制讀主庫
對于一些特殊的業(yè)務場景单匣,采用強制讀主庫。
弊端宝穗,需要把每一個這種情況都找出來户秤,設置成強制走主庫。
3.4 等GTID 方案
MySQL 在執(zhí)行完事務后逮矛,會將該事務的 GTID 會給客戶端鸡号,然后客戶端可以使用該命令去要執(zhí)行讀操作的從庫中執(zhí)行,等待該 GTID须鼎,等待成功后鲸伴,再執(zhí)行讀操作;如果等待超時晋控,則去主庫執(zhí)行讀操作汞窗,或者再換一個從庫執(zhí)行上述流程。
MariaDB 的 MaxScale 就是使用該方案赡译,MaxScale 是 MariaDB 開發(fā)的一個數(shù)據(jù)庫智能代理服務(也支持 MySQL)仲吏,允許根據(jù)數(shù)據(jù)庫 SQL 語句將請求轉(zhuǎn)向目標一個到多個服務器,可設定各種復雜程度的轉(zhuǎn)向規(guī)則蝌焚。
3.5 以不變應萬變
有延遲就有延遲裹唆,對數(shù)據(jù)強一致性要求不高的場景可以放任不管。
點擊此處 即可免費領取更多面試資料