資料庫主從複製,讀寫分離,負載均衡,分庫分表分別表達的什麼概念?


謝邀,這是個好問題,而且這個問題好在即使概念非常容易理解,但是這幾個不同的概念細節太多太多,而且理解了概念,自己要用,又需要做很多的調研評估和開發工作。作為在這個領域爬坑多年的人,我這裡就先介紹下概念,再提供幾個開源工具和雲服務吧。

先來說這些架構解決的問題吧,傳統資料庫如Mysql(以下工具也會以Mysql為主),存在的問題就是單機部署,單進程,這樣就存在一些問題:

  1. 資源利用不靈活,有可能cpu的性能還有富餘,但是磁碟已經頂不住讀壓力或寫壓力了,有可能磁碟的性能還有富餘,但是cpu的性能已經頂不住了。還有可能cpu和磁碟都很富餘,但是寫入的數據量太大,直接撐爆磁碟上限。
  2. 資源有最大上限,cpu最多用到比如64核的機型,磁碟最高几百T,再高的話不好意思,沒有更屌的機器了,但是用戶的數據和查詢是沒有上限的。
  3. 連接池資源的上限,為何要把連接池單獨提出來說,原因就是業務量一大,
  4. 容災類的問題,雖然事務可以保證重啟後數據不丟,但是業務線上跑,重啟等不起。

而這個問題所提的幾個概念,正是對如上傳統資料庫痛點的解決方法。

  1. 主從複製(replication),解決的是容災類的問題,容災需要保證資料庫切換的實時性和數據的一致性,一致性的強弱還催生了幾種不同的複製模式(asynchronous, semisynchronous, group replication)
  2. 讀寫分離(read write spliting),是一種業務類應用解決讀流量單機無法承受的方式,學名叫 scale out ,讀寫分離類的業務是架設在主從複製的基礎上
  3. 負載均衡 ( load balance),也是一個非資料庫的概念,但是在資料庫層面,如果有一個通用的中間層,那麼也適用。

這三者的關係基本可以參考這幾幅圖:

這幅圖的load balance做在了業務層,而讀寫的路由邏輯由業務層在控制。

這幅圖,則由一個通用的中間層解決了讀寫分離的問題,順便也做了資料庫的負載均衡,從這裡看出讀寫分離是資料庫負載均衡的一種解決方式

那麼第三步,如何使用這些特性呢,這幾個特性是好的,但是要使用這些特性,會同時帶來很多的問題,而且先提前聲明一句,目前沒有完美的解決方案,問題如下:

  1. 之前只要管啟動資料庫進程還有掛掉重啟即可,現在還得設置好複製通道,設置容災方式,如何切換,如何回切
  2. 讀寫分離還需要配置中間層,中間層要感知複製通道的方向,感知複製拓撲,還得在切換主從的時候把寫切換過去

最後到了介紹現成工具的時間了,主要推薦以下三款proxy類工具:

Haproxy,Maxscale以及Sqlproxy

提供的方法大同小異,有的能夠通過proxy來建立複製通道,通過proxy來容災,自包含,可以大大簡化運維類的工作量。比較推薦使用Proxy模式來做讀寫分離,而不是業務中間件的形式(如TDDL),因為業務中間件的侵入性比較高,容災和複製通道仍然需要依賴運維手工,而現在比較好的proxy類讀寫分離工具,很多都是自包含的,可以自動建立複製通道。

而一般的雲產品,比如阿里雲,都有開放讀寫分離的功能,如:開通讀寫分離_讀寫分離_用戶指南_雲資料庫 RDS 版-阿里雲

最後,至於分庫分表,這是一個更大的命題了,可以參考我的專欄文章:淺談分散式資料庫該如何學習和實踐 上篇


主從複製
問題:
資料庫伺服器宕機怎麼辦?數據損壞或丟失怎麼辦?服務中斷怎麼辦?
解決辦法:
搞一個備份機,實時或准實時將主資料庫複製到備份機。
當主機宕機時,通過主備切換機制將資料庫訪問請求(主要是查詢請求,如果有更新請求,需要兩台伺服器互為主從)切換到備份機。

一般來說,主從複製是將原資料庫的事物日誌(redo log/binlog等)發送到備份機進行持久化,然後重放。主資料庫宕機時,回丟失非常短時間的數據。

讀寫分離
問題:
如果訪問量增大,超過主伺服器能接受的範圍怎麼辦?
解決辦法:
既然數據已經複製到備份伺服器,能否把查詢的請求發送給從伺服器,減少對主伺服器的負載壓力呢?

這會帶來一個問題,備份資料庫的數據更新會有一個延遲,最新的數據需要一定時間才能同步過來。

如果讀的請求量大到一個備份伺服器無法滿足,那麼可能需要多個備份伺服器。

分庫分表(sharding)
問題:
當訪問量繼續增大,當修改(或查詢)操作的請求量已經超過一台機器的負載能力,如果讓多個伺服器共同處理某個資料庫表所有請求,就會引來分散式事務的問題,解決起來很難。

解決辦法:
讓不同的表或一個表的不同分區(partition)位於多個伺服器中的一個伺服器上,比如一個公司的所有訂單可能很多,但是按照客戶,就可以劃分許多分區,這些分區可以放在不同的伺服器上。

負載均衡
這個概念不是資料庫獨有的概念,是指在由一個集群提供服務時,怎麼把請求分配到集群中的某個伺服器,能夠最小化延遲,最大化集群的利用率。


主從複製:高可用,讀寫分離
讀寫分離:提高性能,1主N從,讓讀不成為系統瓶頸。
分庫:垂直方向提高系統性能。
分表:水平方向提高系統性能。
分區:水平方向提高性能。
比如訂單表,往往是系統瓶頸,那麼可以把訂單表專門用一台伺服器(分庫),採用主從複製,在資料庫出錯時儘快恢復,設置利用HA機制實時把從變成主。性能還不夠,就多搞幾個從伺服器,讀數據從從伺服器讀取。實現讀寫分離。要是還不夠,可以把奇數用戶放一個表,偶數用戶放一個表。還可以把3個月前的訂單放一個表。或者利用分區功能,按用戶id對N取模,放N個分區里。
以上方式都是在不改變資料庫既有技術↓實現的性能提升,大部分應用都可以通過以上方式在傳統資料庫下達到性能要求。
要是還不行,只能從新找出路了,如nosql,分散式資料庫。


說白了就是當下資料庫還不智能,最成熟的還是單機資料庫,分散式資料庫還需要人掌握過多的概念。這些概念都是資料庫分散式的一些方面。

---------------------------------------------

【複製】是【讀寫分離】和【負載均衡】的基礎,是分散式的起點之一,就是在運行過程中保持多台資料庫數據一致不會錯的技術。

從關係上說,分主從複製和主主複製。從一致性來說,分實時複製和非同步複製。從複製方法來說分流複製和邏輯複製。可以有很多劃分方法來說明【複製】,不過說多了也只是名詞而已,有興趣應該選擇一個方面深入研究如何實現的,實現原理是什麼。

【讀寫分離】就是在多台經過複製保持數據一致的資料庫的前提下,對其進行這樣的操作:指定一台(或多台)執行insert/update等寫操作,另外的資料庫只執行select等讀操作,這樣把讀寫的壓力分到不同的資料庫伺服器上,提高系統整體的負載能力。實現方式最簡單的就是代碼里hard code,執行insert/update的時候指定連哪個資料庫,執行select的時候指定連哪個資料庫,更好的方案請自行學習。

【負載均衡】就是一種充分讓多台資料庫發揮效率的技術,比如有1台資料庫負責寫,5台資料庫負責讀。對於這5台讀的資料庫來說,通過某種方式實現在每台資料庫負載都不高的時候,能讓讀的請求盡量均勻地分布在這5台資料庫上,或者某一台很高的時候,盡量把讀的請求放到其他負載相對低的資料庫上。

--------------------------------------------

【分庫分表】是在邏輯層面對多個資料庫(或者多個資料庫集群)進行劃分的意思,是分散式資料庫的起點之二。

最簡單的實現也是hard code在代碼里,想讀寫2017年的數據就讀寫A資料庫(或讀寫通過複製弄出的一組資料庫集群A),想讀寫2016年的數據就讀寫B資料庫(或讀寫通過複製弄出的一組資料庫集群B),要結合2016-2017的數據,就分別讀A和B,然後程序里join起來。

更複雜的是保持多個資料庫(或者資料庫集群)的數據具有事務性,這個涉及到一些分散式一致性演算法。

---------------------------------------------

現在很多資料庫比如TiDB都期望能做到把這些分散式的東西藏起來,資料庫程序默默地處理它。對使用人員來說就是一張表,不管這張表的不同行是否在不同實際的機器里,或者不同列在不同實際的機器里等等。

當然對於資料庫運維人員來說具體的分散式細節還是必須要能了解並控制的。

-----------------------------------------------

不知道題主是站在什麼角度問這個問題,如果站在初學資料庫想了解這些「高大上」名詞的角度,建議紮實資料庫基礎,單機資料庫得弄通透,知道它的原理並能很好控制它,再研究分散式的東西。


主從複製:欽點接班人。
讀寫分離:黨委與政府。
負載均衡:地鐵上車口。
分庫分表:四川和重慶。


既然打了mysql的標籤,就以MySQL為例。

主從複製(replication)就是為了達到資料庫層面的讀寫分離,而實現的一個mysql feature。業務邏輯上將所有的寫操作發到主庫上,從庫承載讀操作。如果有多個從庫需要處理好從庫的讀負載,盡量達到負載均衡。

分庫分表是從業務層面上解決負載過大的問題。試想一個應用在經過幾年的運營後積攢了幾百G幾十T的數據,繼續使用單套資料庫系統的話,可以預知的負載會越來越大,另外業務邏輯也不清晰,將業務邏輯進行解耦,分庫就勢在必行。

分表也是業務層面的,比如一個幾億條記錄的表,如果業務邏輯上需要對這個表有查詢和更新操作,由鎖表和高並發導致的查詢更新的操作效率可能會越來越低。因此,在業務邏輯上作處理將表拆開是一般經常的做法。

主從複製,分庫分表都有優化負載的效果。實際上從某種程度上來說,serverless的流行,在一定程度上是對傳統資料庫橫向擴展的局限在架構設計上的一個妥協。


主從複製即資料庫具備主機備機功能,主機還可用來寫,備機用來提供讀服務,同時實現了主從分離。負載均衡前邊一個apache或nginx做反向代理,後邊2個tomcat處理請求,apache或nginx將請求通過輪巡或者url一致性hash或者加權負載均衡演算法,將請求轉給tomcat整個架構是反向代理負載均衡。當數據量過大一個表一個庫不能解決量以及性能問題,怎麼辦呢?分治法,通過將數據安時間或者hash策略分開,然後相同策略讀取。實現分庫分表。


所做的這些都是為了突破資料庫的瓶頸,主從複製是master到replication的同步過程,讀寫分離就是寫master讀replication,二者需要同步,不然讀寫分離就數據不一致了,當你的單機資料庫不能支撐你的業務的時候,qps太高,或者說容量不夠,那麼你需要分庫分表,當然這是兩個概念,分表也可以單庫分表,但是這樣單機可能成為你的瓶頸,分區也一樣,分庫之後的垮庫事務可能是個大問題,至於負載均衡,就是讓你的請求分發更加合理。


不請自來,這個問題簡單可講,複雜亦可講。
手機扣字就簡單講吧。
主從複製是讀寫分離,負載均衡的前提。
主從複製,就是實時複製資料庫內容到另外一個庫,被複制就是主資料庫,複製過來的就是從資料庫。
程序直接寫主資料庫,讀的話就讀從資料庫了。這就叫做讀寫分離。
我們一般會弄個一拖多,就是一個會有多個從資料庫去同步一個主資料庫,上層使用L4去控制負載均衡確保上層程序查詢的時候能分攤到給個從資料庫上。
另外分庫分表的意思是,我們會根據業務來建立資料庫,如果主從複製的資料庫不在一個數據中心,跨地區。同步對網路要求就高了,所以分庫可以以較高優先順序把重要數據同步優先過來,不重要的就次之了。
因為mysql是關係型的,分表可以細化業務,方便查詢,修改,對優化數據查詢會起到很多幫助。
另,跨數據中心,多重業務的話需要建立主主雙同步,每個主還要考慮高可用性,哦,對了,從資料庫記得單獨分一個出來做備份。


都是折騰出來的,數據產生多了,為了提高資料庫性能才迫不得已而為之。不過傳統的資料庫並沒有意識到這張情況,都是近些年互聯網公司大量的數據才暴露出資料庫的弱點,一些公司已經在開源的資料庫基礎上又開放出了支持高並發大數據量的資料庫,在不侵入應用程序的情況下,自動分庫分表。


(1)讀寫分離:主要是從庫查詢,主庫做增刪改

(2)分庫分表:根據一定的規則將所有數據打散到N個表,CRUD的時候,根據分表欄位的值的路由規則,自動定位到某個庫/某個表

(3)負載均衡:這個不太理解,我的理解是針對查詢,N個從庫的情況下,使用簡單輪訓去選擇從庫查詢,反正所有的從庫的數據都是一樣的


你寫的很多,應該也是搞IT的,那麼我一個個給你講清楚,為了讓你聽懂,就打個比方說的通俗點

資料庫主從複製:主程寫代碼他小弟看著抄,主程寫著寫著跪了,原來看著的小弟繼續寫,不過是在他抄的本地版本上繼續寫

讀寫分離:架構老大說邊讓主程序寫,不過他同時code review時看的是主程旁邊小弟的電腦屏

負載均衡:一主程寫不夠,項目緊時間短,把活拆一拆,再找20個一塊寫,最後攢一塊展示

分庫分表:攢到一塊的程序太臃腫了,按功能模塊拆分成不同軟體,每個軟體還能繼續拆成子模塊


推薦閱讀:

NoSQL 能終結關係資料庫嗎?
mysql開發資料庫命名規範問題?
解釋一下關係資料庫的第一第二第三範式?

TAG:資料庫 | MySQL | 資料庫設計 |