分库分表读写分离
為什么要分庫分表和讀寫分離?
類似淘寶網(wǎng)這樣的網(wǎng)站,海量數(shù)據(jù)的存儲和訪問成為了系統(tǒng)設計的瓶頸問題,日益增長的業(yè)務數(shù)據(jù),無疑對數(shù)據(jù)庫造成了相當大的負載,同時對于系統(tǒng)的穩(wěn)定性和擴展性提出很高的要求。隨著時間和業(yè)務的發(fā)展,數(shù)據(jù)庫中的表會越來越多,表中的數(shù)據(jù)量也會越來越大,相應地,數(shù)據(jù)操作的開銷也會越來越大;另外,無論怎樣升級硬件資源,單臺服務器的資源(CPU、磁盤、內(nèi)存、網(wǎng)絡IO、事務數(shù)、連接數(shù))總是有限的,最終數(shù)據(jù)庫所能承載的數(shù)據(jù)量、數(shù)據(jù)處理能力都將遭遇瓶頸。分表、分庫和讀寫分離可以有效地減小單臺數(shù)據(jù)庫的壓力。
MySQ一主多從,讀寫分離;寫主庫,讀從庫(所有的數(shù)據(jù)庫的數(shù)據(jù)都是一樣的)
數(shù)據(jù)一樣的,那么當數(shù)據(jù)量太大的時查詢還是很慢的
分庫分表的原因
分庫(根據(jù)用戶的ID分庫)
所有數(shù)據(jù)庫的表結構是一樣的,但存儲的數(shù)據(jù)完全不同
真實的開發(fā)環(huán)境以用戶的ID進行分離,每一個庫的數(shù)據(jù)量小,查詢就很快了
無法解決問題:當一個數(shù)據(jù)庫中表中數(shù)據(jù)量過大的時候,查詢依然很慢
分表(根據(jù)存儲數(shù)據(jù)的時間來分)
當一個數(shù)據(jù)庫的數(shù)據(jù)量過大時,必須進行表拆分
分表主要是基于數(shù)據(jù)表的某個字段來將一個表拆分為多個子表,即一個表中的數(shù)據(jù)行拆分到多個子表中去保存,子表存放到同一個數(shù)據(jù)庫的不同表或者不同的數(shù)據(jù)庫中。
分庫分表帶來的問題及解決辦法
任何事情都有兩面性,分庫分表也不例外,如果采用分庫分表,會引入新的的問題
1、分布式事務問題
使用分布式事務中間件解決,具體是通過最終一致性還是強一致性分布式事務,看業(yè)務需求,這里就不多說。
2、跨節(jié)點關聯(lián)查詢 Join 問題
切分之前,我們可以通過Join來完成。而切分之后,數(shù)據(jù)可能分布在不同的節(jié)點上,此時Join帶來的問題就比較麻煩了,考慮到性能,盡量避免使用Join查詢。
解決這個問題的一些方法:
全局表
全局表,也可看做是 “數(shù)據(jù)字典表”,就是系統(tǒng)中所有模塊都可能依賴的一些表,為了避免跨庫Join查詢,可以將 這類表在每個數(shù)據(jù)庫中都保存一份。這些數(shù)據(jù)通常
很少會進行修改,所以也不擔心一致性的問題。
字段冗余
利用空間換時間,為了性能而避免join查詢。例:訂單表保存userId時候,也將userName冗余保存一份,這樣查詢訂單詳情時就不需要再去查詢"買家user表"了。
數(shù)據(jù)組裝
在系統(tǒng)層面,分兩次查詢。第一次查詢的結果集中找出關聯(lián)數(shù)據(jù)id,然后根據(jù)id發(fā)起第二次請求得到關聯(lián)數(shù)據(jù)。最后將獲得到的數(shù)據(jù)進行字段拼裝。
3、跨節(jié)點分頁、排序、函數(shù)問題
跨節(jié)點多庫進行查詢時,會出現(xiàn)Limit分頁、Order by排序等問題。分頁需要按照指定字段進行排序,當排序字段就是分片字段時,通過分片規(guī)則就比較容易定位到指定的分片;
當排序字段非分片字段時,就變得比較復雜了。需要先在不同的分片節(jié)點中將數(shù)據(jù)進行排序并返回,然后將不同分片返回的結果集進行匯總和再次排序,最終返回給用戶。
4、全局主鍵避重問題
如果都用主鍵自增肯定不合理,如果用UUID那么無法做到根據(jù)主鍵排序,所以我們可以考慮通過雪花ID來作為數(shù)據(jù)庫的主鍵,
5、數(shù)據(jù)遷移問題
采用雙寫的方式,修改代碼,所有涉及到分庫分表的表的增、刪、改的代碼,都要對新庫進行增刪改。同時,再有一個數(shù)據(jù)抽取服務,不斷地從老庫抽數(shù)據(jù),往新庫寫,
邊寫邊按時間比較數(shù)據(jù)是不是最新的。
當業(yè)務系統(tǒng)的數(shù)據(jù)容量接近或超過單臺服務器的容量、QPS/TPS接近或超過單個數(shù)據(jù)庫實例的處理極限等此時,往往是采用垂直和水平結合的數(shù)據(jù)拆分方法,把數(shù)據(jù)服務和數(shù)據(jù)存儲分布到多臺數(shù)據(jù)庫服務器上
讀寫分離
什么是讀寫分離
讀寫分離的實質是將應用程序對數(shù)據(jù)庫的讀寫操作分配到多個數(shù)據(jù)庫服務器上,從而降低單臺數(shù)據(jù)庫的訪問壓力。
讀寫分離一般通過配置主從數(shù)據(jù)庫的方式,數(shù)據(jù)的讀取來自從庫,對數(shù)據(jù)庫增加修改刪除操作主庫。
為什么要讀寫分離呢?
通過數(shù)據(jù)庫中間件,可以對數(shù)據(jù)庫進行水平擴展,由原來單臺數(shù)據(jù)庫擴展到多臺數(shù)據(jù)庫,數(shù)據(jù)庫中間件通過路由規(guī)則將數(shù)據(jù)的訪問請求路由到其中一臺數(shù)據(jù)庫上
- 因為數(shù)據(jù)庫的“寫”(寫10000條數(shù)據(jù)到oracle可能要3分鐘)操作是比較耗時的。
- 但是數(shù)據(jù)庫的“讀”(從oracle讀10000條數(shù)據(jù)可能只要5秒鐘)。
- 所以讀寫分離,解決的是,數(shù)據(jù)庫的寫入,影響了查詢的效率。
- 降低了數(shù)據(jù)訪問的瓶頸和單臺數(shù)據(jù)庫的壓力。通過數(shù)據(jù)庫中間件還可以將DBA和研發(fā)進行解耦,提升DBA運維效率。
讀寫分離方案
- 當數(shù)據(jù)庫讀遠大于寫,查詢多的情況,就可以考慮主數(shù)據(jù)負責寫操作,從數(shù)據(jù)庫負責讀操作,一主多重,從而把數(shù)據(jù)讀寫分離
- 可以結合redis等緩存來配合分擔數(shù)據(jù)的讀操作,大大的降低后端數(shù)據(jù)庫的壓力
總結
- 上一篇: 树hash树BtreeB+tree
- 下一篇: Docker中的网络问题