<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一文快速入門分庫分表(必修課)

          共 4429字,需瀏覽 9分鐘

           ·

          2020-10-02 09:55



          之前有不少剛入坑 Java 的粉絲留言,想系統(tǒng)的學習一下分庫分表相關技術,可我一直沒下定決心搞,眼下趕上公司項目在使用 sharing-jdbc ?對現(xiàn)有 MySQL 架構做分庫分表的改造,所以借此機會出一系分庫分表落地實踐的文章,也算是自己對架構學習的一個總結。

          我在網上陸陸續(xù)續(xù)的也看了一些有關于分庫分表的文章,可發(fā)現(xiàn)網上同質化的資料有點多,而且知識點又都比較零碎,還沒有詳細的實戰(zhàn)案例。為了更深入的學習下,我在某些平臺買了點付費課程,看了幾節(jié)課發(fā)現(xiàn)有點經驗的人看還可以,但對于新手入門來說,其實學習難度還是蠻大的。

          為了讓新手也能看得懂,有些知識點我可能會用更多的篇幅加以描述,希望大家不要嫌我啰嗦,等這分庫分表系列文章完結后,我會把它做成 PDF 文檔開源出去,能幫一個算一個吧!如果發(fā)現(xiàn)文中有哪些錯誤或不嚴謹之處,歡迎大家交流指正。

          具體實踐分庫分表之前在啰嗦幾句,回頭復習下分庫分表的基礎概念。

          什么是分庫分表

          其實 分庫分表 是兩個概念,只不過通常分庫與分表的操作會同時進行,以至于我們習慣性的將它們合在一起叫做分庫分表。

          分庫分表是為了解決由于庫、表數(shù)據(jù)量過大,而導致數(shù)據(jù)庫性能持續(xù)下降的問題。按照一定的規(guī)則,將原本數(shù)據(jù)量大的數(shù)據(jù)庫拆分成多個單獨的數(shù)據(jù)庫,將原本數(shù)據(jù)量大的表拆分成若干個數(shù)據(jù)表,使得單一的庫、表性能達到最優(yōu)的效果(響應速度快),以此提升整體數(shù)據(jù)庫性能。

          如何分庫分表

          分庫分表的核心理念就是對數(shù)據(jù)進行切分(Sharding),以及切分后如何對數(shù)據(jù)的快速定位與查詢結果整合。而分庫與分表都可以從:垂直(縱向)和 水平(橫向)兩種緯度進行切分。

          分庫分表

          下邊我們就以訂單相關的業(yè)務舉例,看看如何做庫、表的 垂直水平 切分。

          垂直切分

          垂直切分有 垂直 分庫 和 垂直分表。

          1、垂直分庫

          垂直分庫相對來說是比較好理解的,核心理念就四個字:專庫專用

          按業(yè)務類型對表進行分類,像訂單、支付、優(yōu)惠券、積分等相應的表放在對應的數(shù)據(jù)庫中。開發(fā)者不可以跨庫直連別的業(yè)務數(shù)據(jù)庫,想要其他業(yè)務數(shù)據(jù),對應業(yè)務方可以提供 API 接口,這就是微服務的初始形態(tài)。

          垂直分庫很大程度上取決于業(yè)務的劃分,但有時候業(yè)務間的劃分并不是那么清晰,比如:訂單數(shù)據(jù)的拆分要考慮到與其他業(yè)務間的關聯(lián)關系,并不是說直接把訂單相關的表放在一個庫里這么簡單。

          在一定程度上,垂直分庫似乎提升了一些數(shù)據(jù)庫性能,可實際上并沒有解決由于單表數(shù)據(jù)量過大導致的性能問題,所以就需要配合水平切分方式來解決。

          垂直分庫

          2、垂直分表

          垂直分表是基于數(shù)據(jù)表的列(字段)為依據(jù)切分的,是一種大表拆小表的模式。

          例如:一張 order 訂單表,將訂單金額、訂單編號等訪問頻繁的字段,單獨拆成一張表,把 blob 類型這樣的大字段或訪問不頻繁的字段,拆分出來創(chuàng)建一個單獨的擴展表 work_extend ,這樣每張表只存儲原表的一部分字段,再將拆分出來的表分散到不同的庫中。

          垂直分表

          我們知道數(shù)據(jù)庫是以行為單位將數(shù)據(jù)加載到內存中,這樣拆分以后核心表大多是訪問頻率較高的字段,而且字段長度也都較短,因而可以加載更多數(shù)據(jù)到內存中,來增加查詢的命中率,減少磁盤IO,以此來提升數(shù)據(jù)庫性能。

          垂直切分的優(yōu)點

          • 業(yè)務間數(shù)據(jù)解耦,不同業(yè)務的數(shù)據(jù)進行獨立的維護、監(jiān)控、擴展。

          • 在高并發(fā)場景下,一定程度上緩解了數(shù)據(jù)庫的壓力。

          垂直切分的缺點

          • 提升了開發(fā)的復雜度,由于業(yè)務的隔離性,很多表無法直接訪問,必須通過接口方式聚合數(shù)據(jù)。

          • 分布式事務管理難度增加。

          • 數(shù)據(jù)庫還是存在單表數(shù)據(jù)量過大的問題,并未根本上解決,需要配合水平切分。


          水平切分

          前邊說了垂直切分還是會存在單庫、表數(shù)據(jù)量過大的問題,當我們的應用已經無法在細粒度的垂直切分時, 依舊存在單庫讀寫、存儲性能瓶頸,這時就要配合水平切分一起了,水平切分能大幅提升數(shù)據(jù)庫性能。

          1、水平分庫

          水平分庫是把同一個表按一定規(guī)則拆分到不同的數(shù)據(jù)庫中,每個庫可以位于不同的服務器上,以此實現(xiàn)水平擴展,是一種常見的提升數(shù)據(jù)庫性能的方式。

          這種方案往往能解決單庫存儲量及性能瓶頸問題,但由于同一個表被分配在不同的數(shù)據(jù)庫中,數(shù)據(jù)的訪問需要額外的路由工作,因此系統(tǒng)的復雜度也被提升了。

          例如下圖,訂單DB_1訂單DB_1訂單DB_3 三個數(shù)據(jù)庫內有完全相同的表 order,我們在訪問某一筆訂單時可以通過對訂單的訂單編號取模的方式 訂單編號 mod 3 (數(shù)據(jù)庫實例數(shù)) ,指定該訂單應該在哪個數(shù)據(jù)庫中操作。

          水平分庫

          2、水平分表

          水平分表是在同一個數(shù)據(jù)庫內,把一張大數(shù)據(jù)量的表按一定規(guī)則,切分成多個結構完全相同表,而每個表只存原表的一部分數(shù)據(jù)。

          例如:一張 order 訂單表有 900萬數(shù)據(jù),經過水平拆分出來三個表,order_1order_2order_3,每張表存有數(shù)據(jù) 300萬,以此類推。

          水平分表

          水平分表盡管拆分了表,但子表都還是在同一個數(shù)據(jù)庫實例中,只是解決了單一表數(shù)據(jù)量過大的問題,并沒有將拆分后的表分散到不同的機器上,還在競爭同一個物理機的CPU、內存、網絡IO等。要想進一步提升性能,就需要將拆分后的表分散到不同的數(shù)據(jù)庫中,達到分布式的效果。

          分庫分表

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

          • 解決高并發(fā)時單庫數(shù)據(jù)量過大的問題,提升系統(tǒng)穩(wěn)定性和負載能力。

          • 業(yè)務系統(tǒng)改造的工作量不是很大。

          水平切分的缺點:

          • 跨分片的事務一致性難以保證。

          • 跨庫的join關聯(lián)查詢性能較差。

          • 擴容的難度和維護量較大,(拆分成幾千張子表想想都恐怖)。


          一定規(guī)則是什么

          我們上邊提到過很多次 一定規(guī)則 ,這個規(guī)則其實是一種路由算法,就是決定一條數(shù)據(jù)具體應該存在哪個數(shù)據(jù)庫的哪張表里。

          常見的有 取模算法范圍限定算法

          1、取模算法

          按字段取模(對hash結果取余數(shù) (hash() mod N),N為數(shù)據(jù)庫實例數(shù)或子表數(shù)量)是最為常見的一種切分方式。

          還拿 order 訂單表舉例,先對數(shù)據(jù)庫從 0 到 N-1進行編號,對 order 訂單表中 work_no 訂單編號字段進行取模,得到余數(shù) ii=0存第一個庫,i=1存第二個庫,i=2存第三個庫....以此類推。

          這樣同一筆訂單的數(shù)據(jù)都會存在同一個庫、表里,查詢時用相同的規(guī)則,用 work_no 訂單編號作為查詢條件,就能快速的定位到數(shù)據(jù)。

          優(yōu)點:

          • 數(shù)據(jù)分片相對比較均勻,不易出現(xiàn)請求都打到一個庫上的情況。

          缺點:

          • 這種算法存在一些問題,當某一臺機器宕機,本應該落在該數(shù)據(jù)庫的請求就無法得到正確的處理,這時宕掉的實例會被踢出集群,此時算法變成hash(userId) mod N-1,用戶信息可能就不再在同一個庫中了。

          2、范圍限定算法

          按照 時間區(qū)間ID區(qū)間 來切分,比如:我們切分的是用戶表,可以定義每個庫的 User 表里只存10000條數(shù)據(jù),第一個庫只存 userId 從1 ~ 9999的數(shù)據(jù),第二個庫存 userId 為10000 ~ 20000,第三個庫存 userId 為 20001~ 30000......以此類推,按時間范圍也是同理。

          優(yōu)點:

          • 單表數(shù)據(jù)量是可控的

          • 水平擴展簡單只需增加節(jié)點即可,無需對其他分片的數(shù)據(jù)進行遷移

          • 能快速定位要查詢的數(shù)據(jù)在哪個庫

          缺點:

          • 由于連續(xù)分片可能存在數(shù)據(jù)熱點,比如按時間字段分片,可能某一段時間內訂單驟增,可能會被頻繁的讀寫,而有些分片存儲的歷史數(shù)據(jù),則很少被查詢。

          分庫分表的難點

          1、分布式事務

          由于表分布在不同庫中,不可避免會帶來跨庫事務問題。一般可使用 "三階段提交 "和 "兩階段提交" 處理,但是這種方式性能較差,代碼開發(fā)量也比較大。通常做法是做到最終一致性的方案,如果不苛求系統(tǒng)的實時一致性,只要在允許的時間段內達到最終一致性即可,采用事務補償?shù)姆绞健?/p>

          這里我應用阿里的分布式事務框架Seata 來做分布式事務的管理,后邊會結合實際案例。

          2、分頁、排序、跨庫聯(lián)合查詢

          分頁、排序、聯(lián)合查詢是開發(fā)中使用頻率非常高的功能,但在分庫分表后,這些看似普通的操作卻是讓人非常頭疼的問題。將分散在不同庫中表的數(shù)據(jù)查詢出來,再將所有結果進行匯總整理后提供給用戶。

          3、分布式主鍵

          分庫分表后數(shù)據(jù)庫的自增主鍵意義就不大了,因為我們不能依靠單個數(shù)據(jù)庫實例上的自增主鍵來實現(xiàn)不同數(shù)據(jù)庫之間的全局唯一主鍵,此時一個能夠生成全局唯一ID的系統(tǒng)是非常必要的,那么這個全局唯一ID就叫 分布式ID

          4、讀寫分離

          不難發(fā)現(xiàn)大部分主流的關系型數(shù)據(jù)庫都提供了主從架構的高可用方案,而我們需要實現(xiàn) 讀寫分離 + 分庫分表,讀庫與寫庫都要做分庫分表處理,后邊會有具體實戰(zhàn)案例。

          5、數(shù)據(jù)脫敏

          數(shù)據(jù)脫敏,是指對某些敏感信息通過脫敏規(guī)則進行數(shù)據(jù)轉換,從而實現(xiàn)敏感隱私數(shù)據(jù)的可靠保護,如身份證號、手機號、卡號、賬號密碼等個人信息,一般這些都需要進行做脫敏處理。

          分庫分表工具

          我還是那句話,盡量不要自己造輪子,因為自己造的輪子可能不那么圓,業(yè)界已經有了很多比較成熟的分庫分表中間件,我們根據(jù)自身的業(yè)務需求挑選,將更多的精力放在業(yè)務實現(xiàn)上。

          • sharding-jdbc(當當)
          • TSharding(蘑菇街)
          • Atlas(奇虎360)
          • Cobar(阿里巴巴)
          • MyCAT(基于Cobar)
          • Oceanus(58同城)
          • Vitess(谷歌)

          為什么選 sharding-jdbc

          sharding-jdbc 是一款輕量級 Java 框架,以 jar 包形式提供服務,是屬于客戶端產品不需要額外部署,它相當于是個增強版的 JDBC 驅動;相比之下像 Mycat 這類需要單獨的部署服務的服務端產品,就稍顯復雜了。況且我想把更多精力放在實現(xiàn)業(yè)務,不想做額外的運維工作。

          • sharding-jdbc的兼容性也非常強大,適用于任何基于 JDBCORM 框架,如:JPAHibernateMybatisSpring JDBC Template 或直接使用的 JDBC
          • 完美兼容任何第三方的數(shù)據(jù)庫連接池,如:DBCPC3P0BoneCPDruidHikariCP 等,幾乎對所有關系型數(shù)據(jù)庫都支持。

          不難發(fā)現(xiàn)確實是比較強大的一款工具,而且它對項目的侵入性很小,幾乎不用做任何代碼層的修改,也無需修改 SQL 語句,只需配置待分庫分表的數(shù)據(jù)表即可。

          總結

          簡單的回顧一下分庫分表的基礎知識,接下來的文章會配合實戰(zhàn)項目介紹 sharding-jdbc 在分庫分表中的各個功能點。


          如果對你有用,歡迎 在看、點贊、轉發(fā) ,您的認可是我最大的動力。


          ? ? ? ?
          ???
          新手一看就懂的線程池
          多線程必考的「生產者 - 消費者」模型,看這篇文章就夠了
          萬字長文 | 23 個問題 TCP 疑難雜癥全解析

          覺得不錯,點個在看~

          瀏覽 42
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产影音先锋 | 午夜成人无码免费视频 | 伊人天堂网在线 | 欧美一级AA大片免费看视频 | 青青草伊人在线 |