一、高性能數據庫簡介
1.高性能數據庫方式
讀寫分離:將訪問壓力分散到集群中的多個節點,沒有分散存儲壓力
分庫分表:既可以分散訪問壓力,又可以分散存儲壓力
?
2.為啥不用表分區
- 如果SQL不走分區鍵,很容易出現全表鎖;
- 在分區表實施關聯查詢,就是一個災難;
- 分庫分表,自己掌控業務場景與訪問模式,可控;分區表,工程師寫了一個SQL,自己無法確定MySQL是怎么玩的,不可控;
?
二、讀寫分離——提升數據庫讀性能
可以緩解訂單系統、賬戶系統、購物車系統等等功能mysql的并發壓力
讀寫分離的基本原理是將數據庫的讀寫操作分散到不同的節點
1.讀寫分離的基本實現
數據庫服務器搭建主從集群,一主一從、或者一主多從,數據庫主機負責讀寫操作,從機只負責讀操作。數據庫主機通過復制將數據同步到從機,每臺數據庫服務器都存儲了所有的業務數據。業務服務器將寫操作發給數據庫主機,將讀操作發給數據庫從機。
需要注意的是,這里用的是“主從集群”,而不是“主備集群”。“從機”的“從”可以理解為“仆從”,仆從是要幫主人干活的,“從機”是需要提供讀數據的功能的;而“備機”一般被認為僅僅提供備份功能,不提供訪問功能。
?
2.讀寫分離引起的復雜性
(1)復制延遲
一般會把從庫落后的時間作為一個重點的數據庫指標做監控和報警,正常的時間是在毫秒級別,一旦落后的時間達到了秒級別就需要告警了。
以 MySQL 為例,主從復制延遲可能達到 1 秒,如果有大量數據同步,延遲 1 分鐘也是有可能的。主從復制延遲會帶來一個問題:如果業務服務器將數據寫入到數據庫主服務器后立刻(1 秒內)進行讀取,此時讀操作訪問的是從機,主機還沒有將數據復制過來,到從機讀取數據是讀不到最新數據的,業務上就可能出現問題。解決主從復制延遲有幾種常見的方法:
- 寫操作后的讀操作指定發給數據庫主服務器(緩存標記法)。例如,注冊賬號完成后,登錄時讀取賬號的讀操作也發給數據庫主服務器。這種方式和業務強綁定,對業務的侵入和影響較大,如果哪個新來的程序員不知道這樣寫代碼,就會導致一個 bug。可以利用一個緩存記錄必須讀主的數據。當寫請求發生時:
-
- 寫主庫
- 將哪個庫,哪個表,哪個主鍵三個信息拼裝一個key設置到cache里,這條記錄的超時時間,設置為“主從同步時延”
- 查詢時:
?
-
-
- cache里有這個key,說明1s內剛發生過寫請求,數據庫主從同步可能還沒有完成,此時就應該去主庫查詢
- cache里沒有這個key,說明最近沒有發生過寫請求,此時就可以去從庫查詢
-
?
- 讀從機失敗后再讀一次主機。這就是通常所說的“二次讀取”,二次讀取和業務無綁定,只需要對底層數據庫訪問的 API 進行封裝即可,實現代價較小,不足之處在于如果有很多二次讀取,將大大增加主機的讀操作壓力。
- 關鍵業務讀寫操作全部指向主機,非關鍵業務采用讀寫分離。例如,對于一個用戶管理系統來說,注冊 + 登錄的業務讀寫操作全部訪問主機,用戶的介紹、愛好、等級等業務,可以采用讀寫分離,因為即使用戶改了自己的自我介紹,在查詢時卻看到了自我介紹還是舊的,業務影響與不能登錄相比就小很多,還可以忍受。
- 寫操作完成后,跳轉到無關頁面,類似訂單支付的“支付完成”頁面,其實這個頁面沒有任何有效的信息,就是告訴你支付成功,然后再放一些廣告什么的。你如果想再看剛剛支付完成的訂單,需要手動點一下,這樣就很好地規避了主從同步延遲的問題。
?
(2)分配機制
將讀寫操作區分開來,然后訪問不同的數據庫服務器,一般有兩種方式:程序代碼封裝和中間件封裝。由于數據庫中間件的復雜度要比程序代碼封裝高出一個數量級,一般情況下建議采用程序語言封裝的方式,或者使用成熟的開源數據庫中間件。
- 程序代碼封裝。程序代碼封裝指在代碼中抽象一個數據訪問層,實現讀寫操作分離和數據庫服務器連接的管理。
- 中間件封裝。中間件封裝指的是獨立一套系統出來,實現讀寫操作分離和數據庫服務器連接的管理。對于業務服務器來說,訪問中間件和訪問數據庫沒有區別。中間件需要支持多種編程語言,因為數據庫中間件對業務服務器提供的是標準 SQL 接口。數據庫中間件要支持完整的 SQL 語法和數據庫服務器的協議(例如,MySQL 客戶端和服務器的連接協議),實現比較復雜,細節特別多,很容易出現 bug,需要較長的時間才能穩定。數據庫中間件自己不執行真正的讀寫操作,但所有的數據庫操作請求都要經過中間件,中間件的性能要求也很高。
?
(3)區分連接池
- 數據庫連接池需要區分:讀連接池,寫連接池
- 如果要保證讀高可用,讀連接池要實現故障自動轉移
?
3.從庫的數量
是不是無限制地增加從庫的數量就可以抵抗大量的并發呢?實際上并不是的。因為隨著從庫數量增加,從庫連接上來的 IO 線程比較多,主庫也需要創建同樣多的 log dump 線程來處理復制的請求,對于主庫資源消耗比較高,同時受限于主庫的網絡帶 寬,所以在實際使用中,一般一個主庫最多掛 3~5 個從庫。