目錄
前言
這部分是數據庫相關,思路是從數據庫分庫分表需求思路求解到一個數據庫概念中很難懂的部分--schema。這兩部分本來是不大相關,這裏努力從邏輯上貫通便於更好地去理解schema存在的意義,並且儘量從業務上涵蓋這種邏輯的發展趨勢及痛點。
同時,有些是老生常談的話題,甚至在我之前的blog也有提及很多,這裏重新做一次歸納。
一,爲什麼需要分庫分表
數據庫兩大瓶頸:IO和CPU
其中IO瓶頸就是讀寫,處理請求的網路帶寬不夠或者熱點數據太多,緩存放不下,導致所有的數據請求打到數據庫,每一次查詢產生大量IO降低查詢速度;CPU指執行層我們數據處理的問題,比如SQL大量join,order by,非索引字段查詢會帶來大量CPU負荷,單表數據量過大也會導致CPU利用率過高。
這兩大瓶頸會直接造成數據庫可用連接數減少,用戶的角度感覺就是後臺崩了(服務不可用)。
針對不同瓶頸都要有切實可行的方案去解決或者緩解流量壓力,就算你再人傻錢多,也肯定要做合理的解決方案,否則就會出現某個節點跪了,重要業務取不出來導致全局不可用的情況。以後別人說某app後臺崩了,你就可以知道這其實是業務層壓力過大IO和CPU瓶頸限制導致的部分業務不可用,請求數據發不出來而造成的系統延遲或者服務失靈。
分庫分表的邏輯也很簡單,你數據多搞跨服務器是吧,我把業務數據合理分散管理,最大限度利用硬件資源提供數據服務就好。
二,分庫分表的最好方式
這裏小標題取得有點大,用意是以探討地方式考慮數據庫上雲這一概念,從分庫分表說起。
曾幾何時我們以爲這樣的形式是最好的框架:
fig.1微服務架構
但數據層的割裂必定導致業務層需要更高的複雜度去彌補,再加上數據的流動,維護成本可能更多,所以架構的選擇只能是因業務而已,微服務架構以現在的是叫看肯定不是未來的架構。
我們所需要的是這樣的數據庫:
fig.2 數據庫改進
這個數據庫可以合OLTP和OLAP引擎爲一身,做數據的彈性調度,甚至可以感知業務特點智能地去調度數據產生數據消化數據,這一部分智能在數據層比業務層更有理有效,雲能力的加持更突出數據庫有能力是未來技術潮流的代表,數據層的智能化運維才能真正意味着強人工智能落地的信號,在通訊條件騰飛的未來推進科技的發展。
扯遠回到現實,那麼基礎中的基礎,把一個數據庫合理分庫分表的基本概念就很重要。
水平分庫
概念:以某一字段爲依據,按照一定策略把一個庫中的數據拆分到多個庫中。
注意是一庫分多庫,每個庫都不一樣,庫數據的合集是整個數據。這麼做數據庫變多,肯定會緩解io和CPU瓶頸。一般人的想法就是這個,不過熱點數據固定在表裏,service層就很難做,業務變化可能要不斷調整策略避免跨數據庫查詢,表數據過大就要水平分表
水平分表
概念:以字段爲依據,按照一定策略將一個表的數據拆分到多個表上。
和水平分庫一樣,可以防止單個數據庫讀寫過多,但這麼做會把壓力給到sql優化上,畢竟一次join的消耗是很高的。
垂直分庫
概念:以表爲依據,按照業務歸屬不同,將不同的表分到不同的庫中。
每個庫的結構會不一樣,數據也不一樣,有點像fig.1的按照不同業務分庫,但有時候同一業務不同數據用途的劃分也叫垂直分庫,一些公用的配置表可以拆分到單獨的庫甚至服務化。
垂直分表
概念:以字段爲依據,按照業務歸屬不同,將不同的字段拆到不同的表中。
同一張表,熱點數據和主鍵在一起做熱點數據表可以放到緩存,非熱點數據和外鍵放在一起作爲擴展表,要想獲得所有數據就要關聯兩個表獲取數據。
市面上有很多分庫分表中間件工具jar包,一般原理都是根據容量評估分庫或分表個數,選key執行分表規則,並可以進行擴容
三,schema的存在
schema到底是什麼?
如果查百度知乎,他們會告訴你:
schema是數據庫的組織和結構,模式中包含了schema對象,可以是表(table)、列(column)、數據類型(data type)、視圖(view)、存儲過程(stored procedures)、關係(relationships)、主鍵(primary key)、外鍵(foreign key)等。數據庫模式可以用一個可視化的圖來表示,它顯示了數據庫對象及其相互之間的關係。
其實打開mysql benchmark你會找到用可視化的圖來表示的數據庫模式:
fig.3 mysql schema
概念其實也很清楚了,schema就是用作表示數據庫對象及其相互之間的關係。但這個概念其實遠遠不止於此,在使用過程中show/create/drop schema和show/create/drop databases的SQL語句相同,這就更迷惑了,那麼schema和database的區別是什麼?
然後大家會告訴你schema的定義取決於數據庫供應商,每個數據庫供應商提供的內部schema定義以及實現是不同的:
比如MySQL的文檔中指出,在物理上,模式與數據庫是同義的,所以,模式和數據庫是一回事;Oracle的文檔卻指出,某些對象可以存儲在數據庫中,但不能存儲在schema中。 因此,模式和數據庫不是一回事;SQL Server的schema是內部的一個獨立的實體。
所以說schema是數據庫供應商爲了某些原因創造出服務於整體數據庫的一個概念,那麼這個原因是什麼,爲什麼都要設定schema這個概念呢?這就回到了上邊說的分庫分表的問題。
我們在劃分物理數據庫和表的時候,往往稱爲分片(shard),導致後端數據庫往往有兩種類型,一種爲多Shard,一種爲單Shard,Shard數量滿足2的整數次冪。這樣就導致了,假如有兩張表,一張表爲分區表用於分表,而另外一張表爲普通表不需要分表,則需要在建表是顯式的將兩者分到不同的database中,分區表分到多Shard的database中,而普通表分到單Shard的database中。
然而這樣分片就導致了我前邊提到的問題,一個業務請求的數據可能會影響到不同數據庫,跨庫操作會很影響性能。在mysql中,Schema就是一種解決方案,其實是爲了區分物理database和邏輯database的。面對分片,對上層隱藏database的概念,轉而用Schema進行代替(注意,因爲要對外隱藏整個database,這邊的Schema不僅要代表Schema,還要代表Database,show databases和show schemas是一個結果。)
以下是例子,用於理解概念,具體數據庫要具體結合schema分析
如下圖我們在兩個物理數據庫k1 shards和k2 shards中執行分片,k1被分爲了4片,每一片對應一個邏輯上的database和其對應 的tables;k2被分爲兩片,每一個shard對應一個邏輯上的database和其對應的tables。
k1 shards |
database |
tables |
k2 shards |
database |
tables |
---|---|---|---|---|---|
shard_1_1 | shard_2_1 | ||||
shard_1_2 | shard_2_2 | ||||
shard_1_3 |
|
||||
shard_1_4 |
當我們在k1創建schema db1時對應存儲如下,在新建一個schema後,會在所有的shard上新建一個數據庫,爲k1_db1,這個主要是爲了schema之間的隔離,因爲不同的schema中可能存在同名的表,如果恰巧在同一個shard,同一個數據庫中,就會發生衝突,而在外部看來是不應該衝突的,所以在每個shard上用數據庫進行隔離。
k1 shards |
database |
tables |
k2 shards |
database |
tables |
---|---|---|---|---|---|
shard_1_1 | k1_db1 | shard_2_1 | k2_db1 | ||
shard_1_2 | k1_db1 | shard_2_2 | k2_db1 | ||
shard_1_3 | k1_db1 |
|
|||
shard_1_4 | k1_db1 |
此時再use db1 創建一個普通表a1和創建一個分片表b1就會如下:
k1 shards |
database |
tables |
k2 shards |
database |
tables |
---|---|---|---|---|---|
shard_1_1 | k1_db1 | a1,b1 | shard_2_1 | k2_db1 | |
shard_1_2 | k1_db1 | b1 | shard_2_2 | k2_db1 | |
shard_1_3 | k1_db1 | b1 |
|
||
shard_1_4 | k1_db1 | b1 |
所以你在外面看到的database其實是封裝好的schema,你真正用到的物理上的keyspace和邏輯上的database以及在內部完整轉化了,其中用到的就是上邊的分庫分表原理。
再次聲明,每個數據庫可能設計的分片算法有所不同,以上只是例子去引導如何理解schema這個概念。
四,多shard會產生的問題
首先說,當然還有一系列緩存數據庫做流量分持,使用緩存數據庫又會有許許多多的不一致和遷移問題,這裏不做利弊判斷。
第一,分多shards必定造成數據庫研發上的困難,其實這麼多概念及優化都是爲了能合理解決瓶頸問題,多shard的初衷在此,研發難度自然會提升。
第二,除了研發,運維人員也要合理使用數據庫。衆所周知很多公司的數據庫研發可能其實是DBA,分片提高運維人員的門檻,比如普通表可能只在某個shard上出現,有些表在所有的keyspace上的database都有,有些表是特殊表要怎麼存,多shard情況下怎麼使用索引(二級索引?),怎樣避免跨兩個物理庫去操作等等
第三,SQL下發策略的制定,對原來數據庫中的一切概念多一層Schema的重映射可能性更高,而且每個廠家可能設定策略不同,後邊的研發路徑就更不相同,“借鑑”就很困難。
總結一下,總體來看,分片之路任重道遠,需要投入大量人力物力去開發,而不分片又會導致流量過大瓶頸限制而造成的服務不可用,各大廠商爲了合理設計數據庫引入schema等一系列概念去做內層設計,外層只暴露sql指令給service使用。