分庫分表和數據庫分片方案
數據庫數據量達到千萬級別時查詢效率會很低,分庫分表是一種很有效的解決方案。
垂直划分和水平划分
垂直划分:垂直划分又分為垂直分庫和垂直分表兩種,垂直分庫就是將關聯度低的各種表放在不同的數據庫中,垂直分表是針對表的列進行的,將字段拆到其他表中形成新表,這樣表的記錄就會變小,索引就會降低空間消耗,提升性能。垂直划分業務邏輯清晰便於管理,提升高並發性能,但是表無法連接查詢,涉及分布式事務技術,且不能從本質上減少表的大數據量,還需要借助水平划分。
水平划分:分為分庫分表和庫內分表,庫內分表由於還是共用cpu和IO提升不明顯,將表的記錄按照一定的邏輯分散到多個數據庫多個表中,水平划分徹底解決了大表問題,但還是存在連接查詢不方便,需要引入分布式事務等缺點。
水平划分的數據分片規則主要有兩種:首先是根據不同的時間分庫,比如每一天的數據生成一個數據庫,或者冷熱數據分離,根據數據查詢的頻率分庫,其次是根據某個字段計算hash值來划分,但容易面臨復雜的查詢問題,如果查詢語句中不涉及該字段將導致無法直接定位到數據庫。
分庫分表帶來的問題
1、分布式事務:跨庫事務操作,分布式事務需要協調多個節點,延長了事務的執行時間,並發訪問發生沖突和死鎖的概率增高,對事務一致性要求不高的系統可以不苛求實時一致性,而追求最終一致性即可,也就是事務補償:對數據檢查,日志對比等。
(分布式事務產生的原因可能是因為分庫分表,也可能是因為應用SOA化)
2、連接查詢問題
解決方案有:使用全局表(將各模塊都有可能依賴的表在每個數據庫都保存一份)、字段冗余(一種反范式設計,根據連接查詢業務將要連接查詢的信息加入表中)、數據組裝(將連接查詢拆分成兩次)、將關聯的表放在一起、頻繁的連接查詢可以建立對應的映射表
復雜的查詢還可能用到基因法:
假如要用name查id但是不知道id在哪個庫中,可以讓name在設計時就跟隨一個標記,可以根據這個標記或者標記計算出來的hash值直接拿到id所在的庫位置
3、跨節點分頁、排序、函數
都要在各自的表中執行一遍,然后將結果匯總起來再執行一遍
4、全局主鍵避重問題
可以用uuid(生成一個32個16進制數字)、用一個特殊的表生成主鍵(設置成自增,每次取出這個值)、建立多個ID生成服務器(第一個產生1、3/5、。。。第二個2/4/6.。)、還可以利用緩存(每次只通過表生成一個ID,然后將ID拓展多個值放在內存中等待取用,然后取用完畢繼續生成)、根據實際業務設計一個根據時間生成的字符串(精確到毫秒位,每一個毫秒再設計1000個獨立數)
5、數據擴容和遷徙
如果是根據主鍵范圍分庫的話,擴容很簡單,如果是哈希取模分片,那就要用到一致性hash
分片方案
數據庫分片的邏輯可以封裝在應用端的持久層,也可以在應用和數據之間加一層代理,在中間件中維護分片邏輯。