這篇文章講述的不是Mysql具體的如何實現讀寫分離,而是指什麼時候需要上讀寫分離,及其相關的注意事項。
因為使用者的增多,資料的增多,單機的資料庫往往支撐不住快速發展的業務,所以資料庫叢集就產生了!今天來說說讀寫分離的資料庫叢集方式! 讀寫分離顧名思義就是讀和寫分離了,對應到資料庫叢集一般都是一主一從(一個主庫,一個從庫)或者一主多從(一個主庫,多個從庫),業務伺服器把需要寫的操作都寫到主資料庫中,讀的操作都去從庫查詢。主庫會同步資料到從庫保證資料的一致性。
這種叢集方式的本質就是把訪問的壓力從主庫轉移到從庫,也就是在單機資料庫無法支撐併發讀寫的時候,並且讀的請求很多的情況下適合這種讀寫分離的資料庫叢集。如果寫的操作很多的話不適合這種叢集方式,因為你的資料庫壓力還是在寫操作上,即使主從了之後壓力還是在主庫上和單機區別就不大了。在單機的情況下,一般我們做資料庫優化都會加索引,但是加了索引對查詢有優化,但是會影響寫入,因為寫入資料會更新索引。所以做了主從之後,我們可以單獨的針對從庫(讀庫)做索引上的優化,而主庫(寫庫)可以減少索引而提高寫的效率。
看起來還是很簡單的,但是有兩點要注意:主從同步延遲、分配機制的考慮;
主從同步延遲
主庫有資料寫入之後,同時也寫入在binlog(二進位制日誌檔案)中,從庫是通過binlog檔案來同步資料的,這期間會有一定時間的延遲,可能是1秒,如果同時有大量資料寫入的話,時間可能更長。
這會導致什麼問題呢?比如有一個付款操作,你付款了,主庫是已經寫入資料,但是查詢是到從庫查,從庫裡還沒有你的付款記錄,所以頁面上查詢的時候你還沒付款。那可不急眼了啊,吞錢了這還了得!打電話給客服投訴!
所以為了解決主從同步延遲的問題有以下幾個方法:
1、二次讀取
二次讀取的意思就是讀從庫沒讀到之後再去主庫讀一下,只要通過對資料庫訪問的API進行封裝就能實現這個功能。很簡單,並且和業務之間沒有耦合。但是有個問題,如果有很多二次讀取相當於壓力還是回到了主庫身上,等於讀寫分離白分了。而且如有人惡意攻擊,就一直訪問沒有的資料,那主庫就可能爆了。
2、寫之後的馬上的讀操作訪問主庫
也就是寫操作之後,立馬的讀操作指定訪問主庫,之後的讀操作採取訪問從庫。這就等於寫死了,和業務強耦合了。
3、關鍵業務讀寫都由主庫承擔,非關鍵業務讀寫分離
類似付錢的這種業務,讀寫都到主庫,避免延遲的問題,但是例如改個頭像啊,個人簽名這種比較不重要的就讀寫分離,查詢都去從庫查,畢竟延遲一下影響也不大,不會立馬打客服電話哈哈。
分配機制的考慮
分配機制的考慮也就是怎麼制定寫操作是去主庫寫,讀操作是去從庫讀。
一般有兩種方式:程式碼封裝、資料庫中介軟體。
1、程式碼封裝 程式碼封裝的實現很簡單,就是抽出一箇中間層,讓這個中間層來實現讀寫分離和資料庫連線。講白點就是搞個provider封裝了save,select等通常資料庫操作,內部save操作的dataSource是主庫的,select操作的dataSource是從庫的。
優點:就是實現簡單,並且可以根據業務定製化變化,隨心所欲。
缺點:就是是如果哪個資料庫當機了,發生主從切換了之後,就得修改配置重啟。並且如果你的系統很大,一個業務可能包含多個子系統,一個子系統是java寫的一個子系統用go寫的,這樣的話得分別為不同語言實現一套中間層,重複開發。
2、資料庫中介軟體 就是有一個獨立的系統,專門來實現讀寫分離和資料庫連線管理,業務伺服器和資料庫中介軟體之間是通過標準的SQL協議交流的,所以在業務伺服器看來資料庫中介軟體其實就是個資料庫。
優點:因為是通過sql協議的所以可以相容不同的語言不需要單獨寫一套,並且有中介軟體來實現主從切換,業務伺服器不需要關心這點。
缺點:多了一個系統其實就等於多了一個關心。。如果資料庫中介軟體掛了的話對吧,而且多了一個系統就等於多了一個瓶頸,所以對中介軟體的效能要求也高,並且所有的資料庫操作都要經過它。並且中介軟體實現很複雜,難度比程式碼封裝高多了。
但是有開源的資料庫中介軟體例如Mysql Proxy,Mysql Route,Atlas。
總結
讀寫分離相對而言是比較簡單的,比分表分庫簡單,但是它只能分擔訪問的壓力,分擔不了儲存的壓力,也就是你的資料庫表的資料逐漸增多,但是面對一張表海量的資料,查詢還是很慢的,所以如果業務發展的快資料暴增,到一定時間還是得分庫分表。
但是正常情況下,只要當單機真的頂不住壓力了才會叢集,不要一上來就叢集,沒這個必要。有關於軟體的東西都是越簡單越好,複雜都是形勢所迫。
一般我們是先優化,優化一些慢查詢,優化業務邏輯的呼叫或者加入快取等,如果真的優化到沒東西優化了然後才上叢集,先讀寫分離,讀寫分離之後頂不住就再分庫分表。
如有錯誤歡迎指正! 個人公眾號:yes的練級攻略