一、讀寫分離
因為用戶的增多,數據的增多,單機的數據庫往往支撐不住快速發展的業務,所以數據庫集群就產生了!
讀寫分離顧名思義就是讀和寫分離了,對應到數據庫集群一般都是一主一從(一個主庫,一個從庫)或者一主多從(一個主庫,多個從庫),業務服務器把需要寫的操作都寫到主數據庫中,讀的操作都去從庫查詢。主庫會同步數據到從庫保證數據的一致性。
這種集群方式的本質就是把訪問的壓力從主庫轉移到從庫,適合讀的請求較多的情況下。
在單機的情況下,一般我們做數據庫優化都會加索引,但是加了索引對查詢有優化,但是會影響寫入,因為寫入數據會更新索引。所以做了主從之后,我們可以單獨的針對從庫(讀庫)做索引上的優化,而主庫(寫庫)可以減少索引而提高寫的效率。
看起來還是很簡單的,但是有兩點要注意:主從同步延遲、分配機制的考慮;
主從同步延遲
主庫有數據寫入之后,同時也寫入在binlog(二進制日志文件)中,從庫是通過binlog文件來同步數據的,這期間會有一定時間的延遲,可能是1秒,如果同時有大量數據寫入的話,時間可能更長。
所以為了解決主從同步延遲的問題有以下幾個方法:
1. 二次讀取:意思就是讀從庫沒讀到之后再去主庫讀一下
2. 寫之后的馬上的讀操作訪問主庫
3. 關鍵業務讀寫都由主庫承擔,非關鍵業務讀寫分離
二、分庫分表
主從集群也就是讀寫分離,其實只是分擔了訪問的壓力,但是存儲的壓力沒有解決。
分庫
假設數據庫中有兩張表分別是用戶表和訂單表。如果要分庫的話現在你需要買兩台機子,搞兩個數據庫分別放在兩台機子上,並且一個數據庫放用戶表,一個數據庫放訂單表。
這樣存儲壓力就分擔到兩個服務器上了,但是會帶來新的問題,所以東西變復雜了都會有新的問題產生。。
1. 聯表查詢
也就是join了,之前在一個數據庫里面可以用上join用一條sql語句就可以聯表查詢得到想要的結果,但是現在分為多個數據庫了,所以join用不上了。就比如現在要查注冊時間在2019年之后用戶的訂單信息,你就需要先去數據庫A中用戶表查詢注冊在2019年之后的信息,然后得到用戶id,再拿這些id去數據庫B訂單表中查找訂單信息,然后再拼接這些信息返回。所以等於得多寫一些代碼了。
2. 事務問題
搞數據庫基本上都離不開事務,但是現在不同的數據庫事務就不是以前那個簡單的本地事務了,而是分布式事務了,而引入分布式事務也提高了系統的復雜性。
分表
我們已經做了分庫了,但是現在情況是我們一個表里面的數據太多了,就一不小心你的公司的產品火了,像抖音這種,所有用戶如果就存在一張表里吃不消,所以這時候得分表。分別又分垂直分表和水平分表。
1. 垂直分表
比如我們表有10列,現在一刀切下去,分成了兩張表,其中一張表3列,另一張表7列。
這個一刀切下去讓兩個表分別有幾列不是固定的,垂直分表適合表中存在不常用並且占用了大量空間的字段拆分出去。
就拿頭條的用戶信息,比如用戶表只有用戶id、昵稱、手機號、個人簡介這4個字段。但是手機號和個人簡介這種信息就屬於不太常用的,占用的空間也不小,個人簡介有些人寫了一坨。所以就把手機號和個人簡介這兩列拆分出去。
那垂直分表影響就是之前只要一個查詢的,現在需要兩次查詢才能拿到分表之前的完整用戶表信息。
2. 水平分表
比如現在用戶表有5000萬行數據,我們切5刀,分成5個表,每個表1000萬行數據。
水平分表就適合用戶表行數很多的情況下,一般單表行數超過5000萬就得分表,如果單表的數據比較復雜那可能2000萬甚至1000萬就得分了,這個得看實際情況有些表很簡單可能一億行都不用分。所以當一個表行數超過千萬級別的時候關注一下,如果沒有性能問題就可以再等等看,不要急着分表,因為分表會是帶來很多問題。
水平分表的問題比垂直分表就更煩了。
要考慮怎么切,講的高級點就叫路由:
1. 按id(也就是范圍路由)
比如id 值1-999萬的放一張表,1000萬-1999萬放一張表,一次類推(也就是一段一段)。這個得試的,因為范圍分的大了,可能性能還有問題,范圍分的小了。。那表不得多死。
這種分法的好處就是容易切啊,簡單粗暴,以后新增的數據分表都不會影響到之前的數據,之前的數據都不需要移動。
2. 哈希路由
就是取幾列哈希一下看看數據哪個庫,比如拿id來做哈希,1500取余8等於4,所以這條記錄就放在user_4這個表中,2011取余8等於3,所以這條記錄就放在user_3中。這種分法好處就是分的很均勻,基本上每個表的數據都差不多,但是以后新增數據又得分表了咋辦,以前的數據都得動,比較煩!
3. 搞一張表來存儲路由關系
還是拿用戶表來說,就是弄一個路由表,里面存userId和表編號,表示這個userId是這張user表的的。這種方式也簡單,之后又要分表了之后改改路由表,遷移一部分數據。但是這種方法導致每次查詢都得查兩次,並且如果路由表太大了,那路由表又成為瓶頸了!
三、總結
技術沒有貴賤,不是用了分布式就牛逼,越復雜的系統維護的成本和難度越高,出現問題的幾率越大。這種架構的演化往往都是被用戶所驅動的,可以說是"不得已而為之"。
基本上單機數據庫可以支撐10萬用戶量級別。所以一般情況下像數據庫吃不消就升級硬件,優化數據庫配置、優化代碼、引入redis等。只有在真的不行了才上這些更復雜的東西。