国产精品高清一区二区三区不卡-国产精品一区二区三区免费视频-日韩免费高清一级毛片-亚洲欧美一区二区三区国产精品-日韩欧美一区二区三区不卡视频-亚欧免费视频一区二区三区-亚洲欧美日韩一区成人-欧美日韩视频综合一区无弹窗-精品日韩在线视频一区二区三区-国内精品视频一区二区三区

你好,歡迎進入江蘇優(yōu)軟數(shù)字科技有限公司官網(wǎng)!

誠信、勤奮、創(chuàng)新、卓越

友好定價、專業(yè)客服支持、正版軟件一站式服務(wù)提供

13262879759

工作日:9:00-22:00

美團面試官:說說你對數(shù)據(jù)庫分庫分表的理解?

發(fā)布時間:2024-02-10

瀏覽次數(shù):0

#數(shù)據(jù)分割

關(guān)系型數(shù)據(jù)庫本身更容易成為系統(tǒng)瓶頸,因為單機的存儲容量、連接數(shù)、處理能力都是有限的。 當單表數(shù)據(jù)量達到1000W、100G時,由于查詢維度較多,即使增加從庫、優(yōu)化索引,執(zhí)行較多操作時性能仍然會嚴重下降。 這時候就需要考慮對其進行細分。 分段的目的是減輕數(shù)據(jù)庫的負擔,縮短查詢時間。

數(shù)據(jù)庫分布的核心內(nèi)容無非就是數(shù)據(jù)切分(),以及切分后數(shù)據(jù)的定位和整合。 數(shù)據(jù)分割就是將數(shù)據(jù)分散存儲到多個數(shù)據(jù)庫中,從而減少單個數(shù)據(jù)庫的數(shù)據(jù)量。 通過擴展主機數(shù)量,緩解單個數(shù)據(jù)庫的性能問題,從而達到提高數(shù)據(jù)庫運行性能的目的。

數(shù)據(jù)分割根據(jù)其分割類型可以分為兩種方式:垂直()分割和水平(??ntal)分割。

1.垂直()分割

垂直分段有兩種常見類型:垂直數(shù)據(jù)庫分區(qū)和垂直表分區(qū)。

垂直分庫是基于業(yè)務(wù)耦合,將相關(guān)性較低的不同表存儲在不同的數(shù)據(jù)庫中。 做法類似于將一個大系統(tǒng)拆分成多個小系統(tǒng),按照業(yè)務(wù)分類獨立劃分。 與“微服務(wù)治理”的方法類似,每個微服務(wù)都使用單獨的數(shù)據(jù)庫。 如圖所示:

intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫中的數(shù)據(jù)表的關(guān)系_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些

垂直表分區(qū)基于數(shù)據(jù)庫中的“列”。 如果一個表的字段較多,可以新建一個擴展表,將不常用或字段長度較大的字段拆分到擴展表中。 當字段較多時(例如一張大表有100多個字段),“將大表拆分成小表”更容易開發(fā)和維護,也可以避免跨頁問題。 MySQL底層是通過數(shù)據(jù)頁來存儲的。 占用過多空間的錄制會導(dǎo)致頁面交叉,造成額外的性能開銷。

另外,數(shù)據(jù)庫以行為單位將數(shù)據(jù)加載到內(nèi)存中,使得表中的字段長度更短,訪問頻率更高。 內(nèi)存可以加載更多的數(shù)據(jù),命中率更高,同時減少磁盤IO,從而提高數(shù)據(jù)庫性能。

關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些_關(guān)系庫中的數(shù)據(jù)表的關(guān)系_intellij idea 數(shù)據(jù)庫關(guān)系圖

垂直分割的優(yōu)點:

缺點:

2.水平(??ntal)分割

當應(yīng)用程序很難進行更細粒度的垂直切分,或者切分后的數(shù)據(jù)行數(shù)巨大,且單個數(shù)據(jù)庫的讀、寫、存儲存在性能瓶頸時,就需要水平切分。

水平切分分為庫內(nèi)分片和分庫分片。 基于表中數(shù)據(jù)固有的邏輯關(guān)系,將同一張表根據(jù)不同的情況分散到多個數(shù)據(jù)庫或者多個表中。 每個表只包含部分數(shù)據(jù),從而減少單表數(shù)據(jù)量,達到分布式效果。 如圖所示:

關(guān)系庫中的數(shù)據(jù)表的關(guān)系_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些_intellij idea 數(shù)據(jù)庫關(guān)系圖

數(shù)據(jù)庫內(nèi)部分表只是解決單表數(shù)據(jù)量過大的問題,并沒有將表分布到不同機器的數(shù)據(jù)庫中。 因此,對于減輕MySQL數(shù)據(jù)庫的壓力并沒有太大幫助。 大家仍然在爭奪同一臺物理機器。 CPU、內(nèi)存、網(wǎng)絡(luò)IO最好通過分庫分表的方式解決。

水平切片的優(yōu)點:

缺點:

水平拆分后,同一張表會出現(xiàn)在多個庫/表中,并且每個庫/表的內(nèi)容不同。 幾種典型的數(shù)據(jù)分片規(guī)則是:

1.按數(shù)值范圍

根據(jù)時間間隔或ID間隔進行分割。 例如:將不同月份甚至幾天的數(shù)據(jù)按日期分散到不同的庫中; 將 1 到 9999 的記錄分配給第一個庫,將 10000 到 20000 的記錄分配給第二個庫,依此類推。 從某種意義上說,一些系統(tǒng)中采用的“冷熱數(shù)據(jù)分離”,將一些較少使用的歷史數(shù)據(jù)遷移到其他庫,只在業(yè)務(wù)功能中提供熱數(shù)據(jù)查詢,也是類似的做法。

這樣做的優(yōu)點是:

缺點:

關(guān)系庫中的數(shù)據(jù)表的關(guān)系_intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些

2.根據(jù)數(shù)值取模

一般采用hash mod的分裂方式。 例如,根據(jù)cusno字段將表拆分為4個庫,余數(shù)為0的放入第一個庫,余數(shù)為1的放入第二個庫。 比喻。 這樣,同一用戶的數(shù)據(jù)就會分散到同一個數(shù)據(jù)庫中。 如果查詢條件包含cusno字段,則可以明確定位對應(yīng)的數(shù)據(jù)庫進行查詢。

優(yōu)勢:

缺點:

intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些_關(guān)系庫中的數(shù)據(jù)表的關(guān)系

# 分庫分表引起的問題

分庫分表可以有效消除單機、單庫帶來的性能瓶頸和壓力,突破網(wǎng)絡(luò)IO、硬件資源、連接數(shù)瓶頸。 這也帶來了一些問題。 下面介紹這些技術(shù)挑戰(zhàn)和相應(yīng)的解決方案。

1. 交易一致性問題

分布式交易

當更新的內(nèi)容同時分布在不同的庫中時,不可避免地會出現(xiàn)跨庫事務(wù)問題。 跨分片交易也是分布式交易,沒有簡單的解決方案。 一般可以使用“XA協(xié)議”和“兩階段提交”來處理。

分布式事務(wù)可以最大程度地保證數(shù)據(jù)庫操作的原子性。 但提交交易時,需要多個節(jié)點進行協(xié)調(diào),這就延遲了提交交易的時間點,延長了交易的執(zhí)行時間。 這會導(dǎo)致事務(wù)訪問共享資源時發(fā)生沖突或死鎖的可能性增加。 隨著數(shù)據(jù)庫節(jié)點數(shù)量的增加,這種趨勢會越來越嚴重,從而成為系統(tǒng)在數(shù)據(jù)庫層面橫向擴展的桎梏。

最終一致性

對于那些性能要求高但一致性要求不高的系統(tǒng),往往不要求系統(tǒng)的實時一致性。 只要在允許的時間內(nèi)達到最終一致性,就可以使用事務(wù)補償。 與執(zhí)行過程中發(fā)生錯誤后立即回滾事務(wù)的方法不同,事務(wù)補償是一種事后檢查和補救措施。 一些常見的實現(xiàn)方法包括:數(shù)據(jù)的核對檢查、基于日志的比較、定期與標準數(shù)據(jù)源進行比較。 同步等等。 交易補償也要結(jié)合業(yè)務(wù)系統(tǒng)來考慮。

2、跨節(jié)點關(guān)聯(lián)查詢join問題

在分段之前,系統(tǒng)中很多列表和詳情頁所需的數(shù)據(jù)都可以通過SQL join完成。 分割后,數(shù)據(jù)可能分布在不同的節(jié)點上。 這時候join帶來的問題就比較麻煩了。 考慮到性能,盡量避免使用join查詢。

解決這個問題的一些方法:

1)全局表

全局表也可以看作“數(shù)據(jù)字典表”,是系統(tǒng)中所有模塊都可能依賴的表。 為了避免跨數(shù)據(jù)庫連接查詢,可以在每個數(shù)據(jù)庫中保存此類表的副本。 這些數(shù)據(jù)通常很少被修改,因此無需擔心一致性問題。

2) 現(xiàn)場冗余

典型的反范式設(shè)計使用空間換時間并避免連接查詢以提高性能。 例如:保存訂單表時,也會保存一份冗余副本,這樣在查詢訂單明細時,就不需要再查詢“買家用戶表”了。

但該方法的適用場景也有限,比較適合依賴字段較少的情況。 冗余字段的數(shù)據(jù)一致性也很難保證。 就像上面的訂單表例子一樣,買家進行更改后,是否需要在歷史訂單中同步更新? 這也要結(jié)合實際業(yè)務(wù)場景來考慮。

3)數(shù)據(jù)組裝

在系統(tǒng)層面,查詢分為兩部分。 第一次查詢的結(jié)果重點是找到關(guān)聯(lián)數(shù)據(jù)ID,然后根據(jù)該ID發(fā)起第二次請求獲取關(guān)聯(lián)數(shù)據(jù)。 最后,將獲得的數(shù)據(jù)組裝成字段。

4) 內(nèi)質(zhì)網(wǎng)碎片化

在關(guān)系數(shù)據(jù)庫中,如果能夠先確定表之間的關(guān)聯(lián)性,并將這些關(guān)聯(lián)的表記錄存儲在同一個分片上,就可以更好地避免跨分片連接問題。 在1:1或1:n的情況下,通常是根據(jù)主表的ID主鍵進行拆分。 如下所示:

關(guān)系庫中的數(shù)據(jù)表的關(guān)系_intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些

這樣,Data Node1上的訂單訂單表和訂單明細表就可以通過偏關(guān)聯(lián)的方式進行查詢,在Data Node2上也是如此。

3、跨節(jié)點分頁、排序、功能問題

跨節(jié)點查詢多個數(shù)據(jù)庫時,可能會出現(xiàn)限制分頁、按排序排序等問題。 分頁需要根據(jù)指定字段進行排序。 當排序字段為分片字段時,通過分片規(guī)則更容易定位到指定分片; 當排序字段不是分片字段時,就變得更加復(fù)雜。

數(shù)據(jù)需要先在不同的分片節(jié)點進行排序返回,然后將不同分片返回的結(jié)果集再次匯總排序,最后返回給用戶。 如圖所示:

intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫中的數(shù)據(jù)表的關(guān)系_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些

上圖只取第一頁的數(shù)據(jù),對性能影響不大。 但是,如果獲取的頁面數(shù)量很大,情況就會變得復(fù)雜得多,因為每個分片節(jié)點中的數(shù)據(jù)可能是隨機的。 為了排序的準確性,需要對所有節(jié)點的前N頁數(shù)據(jù)進行排序并合并。 最后,再進行整體排序。 這樣的操作會消耗CPU和內(nèi)存資源,因此頁面數(shù)量越大,系統(tǒng)性能就越差。

使用Max、Min、Sum、Count等函數(shù)進行計算時,也需要先在每個分片上執(zhí)行相應(yīng)的函數(shù),然后對每個分片的結(jié)果集進行匯總并再次計算,最后返回結(jié)果。 如圖所示:

intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫中的數(shù)據(jù)表的關(guān)系_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些

4.全局主鍵回避問題

在分庫分表環(huán)境下,由于表中的數(shù)據(jù)同時存在于不同的數(shù)據(jù)庫中,通常的主鍵值自增就無用武之地了,而某個分區(qū)的自生成ID不能保證數(shù)據(jù)庫是全局唯一的。 因此,需要單獨設(shè)計全局主鍵,避免跨數(shù)據(jù)庫主鍵重復(fù)。 有一些常見的主鍵生成策略:

1)通用唯一標識

UUID的標準形式包含32個十六進制數(shù)字,分為5段,36個字符,形式為8-4-4-4-12。

例如:-e29b-41d4-a716-

UUID為主鍵,這是最簡單的解決方案。 本地生成,性能高,不消耗網(wǎng)絡(luò)時間。 但缺點也很明顯。 由于UUID很長,會占用大量的存儲空間。 另外,創(chuàng)建索引作為主鍵并基于索引進行查詢時也會存在性能問題。 這種情況下,UUID亂序會導(dǎo)致數(shù)據(jù)位置頻繁變化,從而導(dǎo)致。

2)結(jié)合數(shù)據(jù)庫維護主鍵ID表

在數(shù)據(jù)庫中創(chuàng)建一個表:

CREATE TABLE `sequence` (    `id` bigint(20) unsigned NOT NULL auto_increment,    `stub` char(1) NOT NULL default '',    PRIMARY KEY  (`id`),    UNIQUE KEY `stub` (`stub`)  ) ENGINE=MyISAM;

存根字段被設(shè)置為唯一索引。 相同的存根值在表中只有一條記錄,可以同時為多個表生成全局ID。 表內(nèi)容如下:

+-------------------+------+  | id                | stub |  +-------------------+------+  | 72157623227190423 |    a |  +-------------------+------+

請改用存儲引擎,以獲得更高的性能。 采用表級鎖,對表的讀寫是串行的,所以不用擔心并發(fā)時兩次讀取同一個ID值。

當需要全局唯一的64位ID時,執(zhí)行:

REPLACE INTO sequence (stub) VALUES ('a');  SELECT LAST_INSERT_ID();

這兩條語句是級別的,()必須和into在同一個數(shù)據(jù)庫連接下才能得到剛剛插入的新ID。

使用into代替into的好處是可以避免表行數(shù)過大,并且不需要定期清理。

這種方案比較簡單,但是缺點也很明顯:存在單點問題,對DB的依賴強。 當DB異常時,整個系統(tǒng)將不可用。 配置主從可以提高可用性,但是當主庫故障、主從切換時,特殊情況下數(shù)據(jù)一致性很難保證。 另外,性能瓶頸僅限于單個MySQL的讀寫性能。

團隊使用的主鍵生成策略與上面的表解決方案類似,但更好地解決了單點和性能瓶頸的問題。

該方案的總體思路是建立兩臺以上的全局ID生成服務(wù)器,每臺服務(wù)器上只部署一個數(shù)據(jù)庫,每個數(shù)據(jù)庫都有一張表記錄當前的全局ID。 表中ID增長的步長是庫的數(shù)量,起始值按順序錯開,這樣ID的生成就可以散列到每個庫。 如下所示:

intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫中的數(shù)據(jù)表的關(guān)系_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些

ID由兩個數(shù)據(jù)庫服務(wù)器生成并設(shè)置為不同的值。 第一站起始值為1,步長每次增加2。 對方站起始值為2,步長每次增加2。 結(jié)果,第一站生成的ID都是奇數(shù)(1、3、5、7……),第二站生成的ID都是偶數(shù)(2、4、6、8……)。 .)。

該方案將生成ID的壓力平均分配到兩臺機器上。 它還提供系統(tǒng)容錯能力。 如果第一臺機器出現(xiàn)錯誤,可以自動切換到第二臺機器獲取ID。 但它有以下缺點:系統(tǒng)添加機器時,橫向擴展比較復(fù)雜; 每次獲取ID,都需要讀寫DB。 DB的壓力還是很大,只能依靠堆機來提升性能。

可以在解決方案的基礎(chǔ)上繼續(xù)優(yōu)化,使用批量的方式來減少數(shù)據(jù)庫的寫入壓力,每次獲取一個范圍的ID號段,使用完后再去數(shù)據(jù)庫獲取,這樣可以大大減少數(shù)據(jù)庫的壓力。 如下所示:

關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些_intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫中的數(shù)據(jù)表的關(guān)系

或者使用兩個DB來保證可用性。 數(shù)據(jù)庫中僅存儲當前最大ID。 ID生成服務(wù)每次批量拉取6個ID,先改為5個。應(yīng)用訪問ID生成服務(wù)時,不需要訪問數(shù)據(jù)庫,從號段緩存中依次調(diào)度ID 0~5 。 這些ID下發(fā)后,將其更改為11,下次可以分配ID 6~11。 這樣一來,數(shù)據(jù)庫的壓力就減少到原來的1/6。

3)分布式自增ID算法

該算法解決了分布式系統(tǒng)生成全局ID的需求,生成64位的Long類型數(shù),組成:

這樣做的好處是:毫秒數(shù)處于較高水平,生成的ID一般按照時間趨勢增加; 不依賴第三方系統(tǒng),穩(wěn)定性和效率高。 理論上QPS約為409.6w/s(1000*2^12)。 并且整個分布式系統(tǒng)不會出現(xiàn)ID沖突; 可以根據(jù)自己的業(yè)務(wù)靈活分配比特。

缺點是它嚴重依賴機器時鐘。 如果時鐘被調(diào)回,可能會導(dǎo)致重復(fù)的 ID 生成。

總結(jié)

結(jié)合數(shù)據(jù)庫和獨特的ID解決方案,可以參考業(yè)界比較成熟的解決方案:Leaf——美團點評的分布式ID生成系統(tǒng),兼顧了高可用、容災(zāi)、分布式降頻等問題。

5. 數(shù)據(jù)遷移和擴展問題

當業(yè)務(wù)快速發(fā)展,面臨性能和存儲瓶頸時,就會考慮分片設(shè)計。 這時候就不可避免地要考慮歷史數(shù)據(jù)遷移的問題。 一般的做法是先讀取歷史數(shù)據(jù),然后按照指定的分片規(guī)則將數(shù)據(jù)寫入到各個分片節(jié)點。 另外,還需要根據(jù)當前的數(shù)據(jù)量和QPS以及業(yè)務(wù)發(fā)展的速度進行容量規(guī)劃,計算出大概需要的分片數(shù)量(一般建議單表的數(shù)據(jù)量)單個分片不應(yīng)超過1000W)

如果采用數(shù)值范圍分片,只需要增加節(jié)點擴容即可,無需遷移分片數(shù)據(jù)。 如果采用數(shù)值模分片,考慮后期擴容問題會相對麻煩。

#何時考慮分段?

我們來談?wù)勈裁磿r候需要考慮數(shù)據(jù)分割。

1、可以的話盡量不要剪。

并不是所有的表都需要拆分,主要看數(shù)據(jù)的增長速度。 細分會在一定程度上增加業(yè)務(wù)的復(fù)雜性。 數(shù)據(jù)庫除了承載數(shù)據(jù)存儲和查詢之外,輔助業(yè)務(wù)更好地實現(xiàn)需求也是其重要任務(wù)之一。

除非絕對必要,否則不要使用分庫分表的大招,避免“過度設(shè)計”和“過早優(yōu)化”。 分庫分表之前,不要為了分而分。 盡量先做能做的,比如升級硬件、升級網(wǎng)絡(luò)、讀寫分離、索引優(yōu)化等。當數(shù)據(jù)量達到單表的瓶頸時,可以考慮分庫分表。

2、數(shù)據(jù)量過大,正常運維影響業(yè)務(wù)訪問。

這里所說的運維是指:

1)對于數(shù)據(jù)庫備份,如果單表太大,備份時會需要大量的磁盤IO和網(wǎng)絡(luò)IO。例如通過網(wǎng)絡(luò)傳輸1T數(shù)據(jù),占用50MB,則需要20000秒完成傳輸。 整個過程的風(fēng)險是比較高的。

2)當對大表進行DDL修改時,MySQL會鎖定整個表。 這個時間會很長。 這段時間業(yè)務(wù)無法訪問表,影響很大。 如果使用pt---,使用過程中會創(chuàng)建觸發(fā)器和影子表,這也會花費很長時間。 在此操作期間,計為風(fēng)險時間。 拆分數(shù)據(jù)表并減少總量可以幫助降低這種風(fēng)險。

3)大表訪問更新頻繁,更容易出現(xiàn)鎖等待。分割數(shù)據(jù),以空間換取時間,變相降低訪問壓力

3、隨著業(yè)務(wù)的發(fā)展,有些領(lǐng)域需要進行垂直拆分。

例如,如果項目開始時設(shè)計的用戶表如下:

id                   bigint             #用戶的IDname                 varchar            #用戶的名字last_login_time      datetime           #最近登錄時間personal_info        text               #私人信息.....                                   #其他信息字段

在項目初期,這樣的設(shè)計滿足簡單的業(yè)務(wù)需求,有利于快速迭代開發(fā)。 當業(yè)務(wù)快速發(fā)展時,用戶數(shù)量從10萬激增至10億。 用戶非?;钴S,每次登錄都會更新字段,導(dǎo)致用戶表不斷更新,壓力很大。 其他字段:id、name 不變或很少更新。 從業(yè)務(wù)角度來說,需要將它們拆分出來,創(chuàng)建一個新表。

屬性的更新和查詢頻率較低,并且文本字段占用太多空間。 這時候就需要對表格進行垂直分割。

4、數(shù)據(jù)量快速增長

隨著業(yè)務(wù)的快速發(fā)展,單表數(shù)據(jù)量會不斷增長。 當性能接近瓶頸時,就需要考慮水平分片,建立獨立的數(shù)據(jù)庫和表。此時,必須選擇合適的分片規(guī)則并提前估算數(shù)據(jù)容量。

5. 安全性和可用性

不要把雞蛋放在同一個籃子里。 縱向切分是在業(yè)務(wù)層面進行的,將不相關(guān)業(yè)務(wù)的數(shù)據(jù)庫分開。 由于每個業(yè)務(wù)的數(shù)據(jù)量和訪問量都不同,不能因為一項業(yè)務(wù)影響數(shù)據(jù)庫而牽連到其他業(yè)務(wù)。 使用水平切片,當數(shù)據(jù)庫出現(xiàn)問題時,不會影響100%的用戶。 每個數(shù)據(jù)庫只承載部分業(yè)務(wù)數(shù)據(jù),可以提高整體可用性。

#案例分析

1、用戶中心業(yè)務(wù)場景

用戶中心是一個很常見的業(yè)務(wù),主要提供用戶注冊、登錄、查詢/修改等功能。 其核心表是:

User(uid, login_name, passwd, sex, age, nickname)
uid為用戶ID, 主鍵login_name, passwd, sex, age, nickname, 用戶屬性

任何脫離業(yè)務(wù)的建筑設(shè)計都是流氓。 在分庫分表之前,需要梳理一下業(yè)務(wù)場景需求:

1、用戶側(cè):前端訪問,訪問量較大,需要保證高可用性和高一致性。 需求主要有兩類:

用戶登錄:通過/電話/郵箱查詢用戶信息,1%的請求屬于此類 用戶信息查詢:登錄后通過uid查詢用戶信息,99%的請求屬于此類

2、運營端:后端訪問,支持運營需求,根據(jù)年齡、性別、登錄時間、注冊時間等進行分頁查詢,屬于內(nèi)部系統(tǒng),訪問量不大,對可用性和一致性要求不高。

2、水平分割法

當數(shù)據(jù)量越來越大時,就需要對數(shù)據(jù)庫進行水平分段。 上述分割方法包括“基于數(shù)值范圍”和“基于數(shù)值模”。

“基于取值范圍”:基于主鍵uidintellij idea 數(shù)據(jù)庫關(guān)系圖,將數(shù)據(jù)按照uid的范圍水平劃分到多個數(shù)據(jù)庫中。 例如:user-db1存儲uid范圍為0~1000w的數(shù)據(jù),user-db2存儲uid范圍為1000w~的數(shù)據(jù)。

優(yōu)點是:擴展簡單。 如果容量不夠,只需添加新的db即可。

缺點是請求量不均勻。 一般新注冊的用戶會比較活躍,所以新的user-db2的負載會比user-db1更高,導(dǎo)致服務(wù)器利用率不平衡。

“基于數(shù)值取模”:同樣以主鍵uid作為劃分依據(jù),根據(jù)uid的取模值將數(shù)據(jù)水平拆分到多個數(shù)據(jù)庫中。 例如:user-db1 存儲 uid 數(shù)據(jù)模 1,user-db2 存儲 uid 數(shù)據(jù)模 0。

優(yōu)點是:數(shù)據(jù)量和請求量分布均勻

缺點是:擴容麻煩。 當容量不夠時,需要添加新的db。 需要考慮數(shù)據(jù)的平滑遷移。

3.非uid查詢方法

水平切分后,可以很好的滿足通過uid查詢的需求,可以直接路由到具體的數(shù)據(jù)庫。 例如,對于基于非 uid 的查詢,不知道應(yīng)該訪問哪個庫。 這樣的話就需要遍歷所有的庫,性能會下降很多。

對于用戶側(cè),可以采用“建立非uid屬性到uid的映射關(guān)系”的方案; 對于運營端,可以采用“前后端分離”的解決方案。

建立非uid屬性與uid的映射關(guān)系

1)映射關(guān)系

例如:如果無法直接定位到數(shù)據(jù)庫,可以建立→uid映射關(guān)系,使用索引表或者緩存來存儲。 訪問時,先通過映射表查詢對應(yīng)的uid,然后通過uid定位到具體的庫。

映射表只有兩列,可以承載大量數(shù)據(jù)。 當數(shù)據(jù)量太大時intellij idea 數(shù)據(jù)庫關(guān)系圖,還可以對映射表進行水平分割。 這類kv格式的索引結(jié)構(gòu)可以利用緩存來優(yōu)化查詢性能,而且映射關(guān)系不會頻繁變化,緩存命中率會很高。

2) 遺傳法

分庫基因:如果通過uid將庫分為8個庫,并且使用uid%8進行路由,那么uid的最后3位決定了這行User數(shù)據(jù)落在哪個庫上,那么這3位可以看成子庫基因。

上述映射關(guān)系方式需要額外存儲映射表,當通過非uid字段查詢時,需要額外的數(shù)據(jù)庫或緩存訪問。 如果想消除冗余的存儲和查詢,可以使用f函數(shù)獲取該基因作為uid的子庫基因。 生成uid時,參考上面介紹的分布式唯一ID生成方案,加上最后3位值=f()。 查詢時,只需計算f()%8的值即可定位到具體的庫。 但這需要提前進行容量規(guī)劃,預(yù)估未來幾年需要將數(shù)據(jù)量劃分為多少個數(shù)據(jù)庫,并預(yù)留一定數(shù)量的數(shù)據(jù)庫基因位。

關(guān)系庫中的數(shù)據(jù)表的關(guān)系_intellij idea 數(shù)據(jù)庫關(guān)系圖_關(guān)系庫數(shù)據(jù)系統(tǒng)有哪些

前臺與后臺分離

對于用戶端來說,主要需求是關(guān)注單行查詢。 需要建立/phone/email到uid的映射關(guān)系,可以解決這些字段的查詢問題。

操作方面,有很多批量分頁、各種條件的查詢。 此類查詢需要大量計算,返回大量數(shù)據(jù),對數(shù)據(jù)庫性能消耗較高。 此時,如果與用戶側(cè)共享同一批服務(wù)或數(shù)據(jù)庫,少量的后臺請求可能會占用大量的數(shù)據(jù)庫資源,導(dǎo)致用戶側(cè)訪問性能下降或超時。

此類業(yè)務(wù)最好采用“前后端分離”的方案。 運營側(cè)后端業(yè)務(wù)抽取獨立的數(shù)據(jù)庫和數(shù)據(jù)庫,解決與前端業(yè)務(wù)系統(tǒng)的耦合。 由于運營方對可用性和一致性要求不高,因此不需要訪問實時庫,而是通過數(shù)據(jù)的異步同步來訪問運營庫。 當數(shù)據(jù)量較大時,還可以使用ES搜索引擎或Hive來滿足后臺復(fù)雜的查詢方式。

# 支持分庫分表中間件

站在巨人的肩膀上,可以省掉很多力氣。 目前有一些比較成熟的分庫分表開源解決方案:

如有侵權(quán)請聯(lián)系刪除!

13262879759

微信二維碼