首頁>資訊>

原文連結:https://mp.weixin.qq.com/s/6zMc-IVBGRI788694ZKQig

大家好呀!

今天和小夥伴們聊聊讀寫分離以及分庫分表。相信很多小夥伴們對於這兩個概念已經比較熟悉了。

如果你之前不太瞭解這兩個概念,那我建議你搞懂之後,可以把自己對於讀寫分離以及分庫分表的理解講給你的同事/朋友聽聽。

讀寫分離何為讀寫分離?

見名思義,根據讀寫分離的名字,我們就可以知道:讀寫分離主要是為了將對資料庫的讀寫操作分散到不同的資料庫節點上。 這樣的話,就能夠小幅提升寫效能,大幅提升讀效能。

我簡單畫了一張圖來幫助不太清楚讀寫分離的小夥伴理解。

讀寫分離

一般情況下,我們都會選擇一主多從,也就是一臺主資料庫負責寫,其他的從資料庫負責讀。主庫和從庫之間會進行資料同步,以保證從庫中資料的準確性。這樣的架構實現起來比較簡單,並且也符合系統的寫少讀多的特點。

讀寫分離會帶來什麼問題?如何解決?

讀寫分離對於提升資料庫的併發非常有效,但是,同時也會引來一個問題:主庫和從庫的資料存在延遲,比如你寫完主庫之後,主庫的資料同步到從庫是需要時間的,這個時間差就導致了主庫和從庫的資料不一致性問題。這也就是我們經常說的 主從同步延遲

1.強制將讀請求路由到主庫處理。

既然你從庫的資料過期了,那我就直接從主庫讀取嘛!這種方案雖然會增加主庫的壓力,但是,實現起來比較簡單,也是我瞭解到的使用最多的一種方式。

比如 Sharding-JDBC 就是採用的這種方案。透過使用 Sharding-JDBC 的 HintManager 分片鍵值管理器,我們可以強制使用主庫。

HintManager hintManager = HintManager.getInstance();hintManager.setMasterRouteOnly();// 繼續JDBC操作

對於這種方案,你可以將那些必須獲取最新資料的讀請求都交給主庫處理。

2.延遲讀取。

還有一些朋友肯定會想既然主從同步存在延遲,那我就在延遲之後讀取啊,比如主從同步延遲 0.5s,那我就 1s 之後再讀取資料。這樣多方便啊!方便是方便,但是也很扯淡。

另外,《MySQL 實戰 45 講》[1]這個專欄中的《讀寫分離有哪些坑?》[2]這篇文章還介紹了很多其他比較實際的解決辦法,感興趣的小夥伴可以自行研究一下。

如何實現讀寫分離?

不論是使用哪一種讀寫分離具體的實現方案,想要實現讀寫分離一般包含如下幾步:

部署多臺資料庫,選擇一種的一臺作為主資料庫,其他的一臺或者多臺作為從資料庫。保證主資料庫和從資料庫之間的資料是實時同步的。系統將寫請求交給主資料庫處理,讀請求交給從資料庫處理。

落實到專案本身的話,常用的方式有兩種:

1.代理方式

讀寫分離-代理層

我們可以在應用和資料中間加了一個代理層。應用程式所有的資料請求都交給代理層處理,代理層負責分離讀寫請求,將它們路由到對應的資料庫中。

提供類似功能的中介軟體有 MySQL Router(官方)、Atlas(基於 MySQL Proxy)、MaxscaleMyCat

2.元件方式

在這種方式中,我們可以透過引入第三方元件來幫助我們讀寫請求。

這也是我比較推薦的一種方式。這種方式目前在各種網際網路公司中用的最多的,相關的實際的案例也非常多。如果你要採用這種方式的話,推薦使用 sharding-jdbc ,直接引入 jar 包即可使用,非常方便。同時,也節省了很多運維的成本。

你可以在 shardingsphere 官方找到sharding-jdbc 關於讀寫分離的操作[3]

分庫分表

讀寫分離主要應對的是資料庫讀併發,沒有解決資料庫儲存問題。試想一下:如果 MySQL 一張表的資料量過大怎麼辦?

換言之,我們該如何解決 MySQL 的儲存壓力呢?

答案之一就是 分庫分表

何為分庫?

分庫 就是將資料庫中的資料分散到不同的資料庫上。

下面這些操作都涉及到了分庫:

你將資料庫中的使用者表和使用者訂單表分別放在兩個不同的資料庫。由於使用者表資料量太大,你對使用者表進行了水平切分,然後將切分後的 2 張使用者表分別放在兩個不同的資料庫。何為分表?

分表 就是對單表的資料進行拆分,可以是垂直拆分,也可以是水平拆分。

何為垂直拆分?

簡單來說,垂直拆分是對資料表列的拆分,把一張列比較多的表拆分為多張表。

舉個例子:我們可以將使用者資訊表中的一些列單獨抽出來作為一個表。

何為水平拆分?

簡單來說,水平拆分是對資料錶行的拆分,把一張行比較多的表拆分為多張表。

舉個例子:我們可以將使用者資訊表拆分成多個使用者資訊表,這樣就可以避免單一表資料量過大對效能造成影響。

《從零開始學架構》[4] 中的有一張圖片對於垂直拆分和水平拆分的描述還挺直觀的。

什麼情況下需要分庫分表?

遇到下面幾種場景可以考慮分庫分表:

單表的資料達到千萬級別以上,資料庫讀寫速度比較緩慢(分表)。資料庫中的資料佔用的空間越來越大,備份時間越來越長(分庫)。應用的併發量太大(分庫)。分庫分表會帶來什麼問題呢?

記住,你在公司做的任何技術決策,不光是要考慮這個技術能不能滿足我們的要求,是否適合當前業務場景,還要重點考慮其帶來的成本。

引入分庫分表之後,會給系統帶來什麼挑戰呢?

join 操作 :同一個資料庫中的表分佈在了不同的資料庫中,導致無法使用 join 操作。這樣就導致我們需要手動進行資料的封裝,比如你在一個數據庫中查詢到一個數據之後,再根據這個資料去另外一個數據庫中找對應的資料。事務問題 :同一個資料庫中的表分佈在了不同的資料庫中,如果單個操作涉及到多個數據庫,那麼資料庫自帶的事務就無法滿足我們的要求了。分散式 id :分庫之後, 資料遍佈在不同伺服器上的資料庫,資料庫的自增主鍵已經沒辦法滿足生成的主鍵唯一了。我們如何為不同的資料節點生成全域性唯一主鍵呢?這個時候,我們就需要為我們的系統引入分散式 id 了。......

另外,引入分庫分表之後,一般需要 DBA 的參與,同時還需要更多的資料庫伺服器,這些都屬於成本。

分庫分表有沒有什麼比較推薦的方案?

ShardingSphere 專案(包括 Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar)是噹噹捐入 Apache 的,目前主要由京東數科的一些巨佬維護。

ShardingSphere 絕對可以說是當前分庫分表的首選!ShardingSphere 的功能完善,除了支援讀寫分離和分庫分表,還提供分散式事務、資料庫治理等功能。

另外,ShardingSphere 的生態體系完善,社群活躍,文件完善,更新和釋出比較頻繁。

艿艿之前寫了一篇分庫分表的實戰文章,各位朋友可以看看:《芋道 Spring Boot 分庫分表入門》 。

除了分庫分表,還有其他方法麼?

另外的話,除了這分庫分表種解決方案之外,目前還有很多公司使用了目前比較火的一個開源的分散式關係型資料庫 TiDB

對於,TiDB 來說根本不用擔心資料庫儲存壓力,可以為我們節省很多事情。

並且,TiDB 天然支援水平擴容或者縮容、金融級高可用,並且,相容 MySQL 5.7 協議和 MySQL 生態。非常適合高可用、強一致要求較高、資料規模較大等各種應用場景。

4
最新評論
  • 3本作者大大最好的一本小說,劇情讓人拍手叫好,連看三遍也不膩
  • 小說:你對我的傷害