ShardingJdbc分庫分表實戰案例解析(上)

2020-09-20 劉能搬磚

在對諸如訂單、交易、支付等實時在線業務系統的研發、維護過程中,隨著業務量的快速增長,我們經常會遇到由於關係型資料庫(如:MySql)單表數據量增長過大而引發的線上事故;雖然這些事故多數時候是由於不合理的慢SQL而引起的系統雪崩,但有時也會出現由於資料庫熱點塊IO爭用而引發的系統性性能下降。總之,單表數據量的無限增長總是會在這樣或那樣的情況下增加系統的不穩定性因素。

所以在大規模實時系統的設計中,除了重點考慮應用結構的分布式化外,往往也不應該忽略資料庫實時存儲、計算能力擴展性方面的考慮。目前解決實時數據增長一般有兩種思路:一種是直接採用分布式資料庫(例如:Tidb、OceanBase之類);另一種是對關係型資料庫進行分庫分表來最大化利用現有資料庫的實時計算能力。絕大部分情況下,後一種方案往往會更現實一些。

本文的主要內容就是通過模擬一個交易系統的訂單庫,來具體演示如何通過ShardingJdbc實現交易訂單數據的分庫分表存儲。在這個過程中會到涉及分庫分表實踐的三種主要場景:1、新系統在設計之初直接使用分庫分表方案;2、歷史系統運行一段時間後如何平滑地實施分庫分表;3、對現有分庫分表邏輯的Scaling操作(包括減少分表、增加分表)涉及的數據遷移問題。

Spring Boot集成ShardingJdbc實現分庫分表

交易系統的訂單數據是分庫分表的一個非常典型場景,由於交易系統對單條數據的實時處理性能要求很高,所以一旦單個訂單表數據量規模達到10億+,就很容易出現由於資料庫熱點塊IO爭用而導致的性能下降,也很容易出現個別不謹慎的SQL操作而引起的系統性雪崩。

但一旦決定實施分庫分表就要提前做好存儲規劃,並對未來數據增長的規模進行一定的評估,同時做好未來增加分庫、增加分表的系統Scaling方案。此外,分庫分表的實施還要考慮應用的接入難度,分庫分表的細節邏輯應該對應用透明;所以一般來說我們需要一個中間代理層來屏蔽分庫分表對應用程式本身帶來的侵入。

目前在Java社區中比較知名的分庫分表代理組件就是ShardingJdbc(目前已被集成在Apache開源項目 ShardingSphere之中),ShardingJdbc本質上是一個輕量級的JDBC驅動代理,在使用的過程中只需要依賴相關Jar包即可,並不需要額外部署任何服務。通過系統配置文件就可以實現分庫分表邏輯的定義,並實現應用透明代理訪問。

接下來,我們以Spring Boot為例演示如何集成ShardingJdbc實現對交易訂單的分庫分表操作,具體步驟如下:

1)、訂單數據的分庫分表規劃

在系統設計之初,如果能夠預見到未來數據量的增長規模,那麼提前做好分庫分表規劃是非常有遠見的。從分庫分表的形式上來說,一般可以有兩類規劃方式:1)、單庫水平分表,如果單一資料庫計算能力比較強,可以在同一個庫中進行數據表的水平拆分;2)、分庫+分表,如果數據規模爆炸式增長,單庫的計算資源有限,為了提升資料庫的整體計算處理性能,也可以同時實現多個庫的分庫分表存儲。

在本文的實例中,我們將訂單數據分庫分表規劃為:1)、資料庫節點2個(ds0、ds1);2)、每個庫的分表數為32張表(0~31)。訂單表的整體數據分庫分表邏輯是根據訂單表中的「user_id欄位%2」實現分庫;然後在分庫邏輯的基礎上根據訂單表中的「order_id欄位%32」實現水平分表。例如,有條user_id為1001、訂單編號為20200713001的訂單數據,根據上述分庫分表規則1001%2=1,20200713001%32=9,那麼該數據將存儲在ds1庫中的第9個分表。

具體的訂單邏輯表結構如下:

create table t_order ( id bigint not null primary key auto_increment, order_id bigint comment &39;, trade_type varchar (30) comment &39;, amount bigint comment &39;, currency varchar (10) comment &39;, status varchar (2) comment &39;, channel varchar (10) comment &39;, trade_no varchar (32) comment &39;, user_id bigint (60) comment &39;, update_time timestamp null default current_timestamp on update current_timestamp comment &39;, create_time timestamp null default current_timestamp comment &39;, remark varchar(128) comment &39;, key unique_idx_pay_id ( order_id ), key idx_user_id ( user_id ), key idx_create_time ( create_time ));alter table t_order comment &39;;

以上邏輯表的具體分表形式為t_order_{0~31},分別分布在ds0、ds1兩個資料庫節點中。

2)、創建實驗工程代碼結構

首先創建一個基於Maven構建的Spring Boot項目,併集成MyBatis資料庫訪問框架,代碼結構如下:

如上圖所示,我們創建了一個基於Spring Boot的基本工程,並在集成了基於Mybatis的資料庫訪問功能。此外該工程還實現了單元/集成測試代碼的分離管理。

3)、SpringBoot+ShardingJdbc實現訂單分庫分表規則配置

接下來我們來看下在Spring Boot項目中如何集成ShardingJdbc,並按照規劃的分庫分表規則進行具體的配置。

首先引入ShardingJdbc針對Spring Boot項目的starter依賴包,具體如下:

<!-- 引入Sharding-JDBC Spring Boot依賴組件 --><!-- Sharding-JDBC For Spring Boot Start --><dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>${sharding-sphere.version}</version></dependency><!-- for spring namespace --><dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-namespace</artifactId> <version>${sharding-sphere.version}</version></dependency><!-- Sharding-JDBC For Spring Boot End -->

引入Spring Boot Starter依賴後,ShardingJdbc會使用自己的數據源配置邏輯,為避免衝突需要在主類中排除掉默認的數據源自動配置類,具體如下:

//排除掉默認的數據源自動配置類@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})public class OrderServerApplication { public static void main(String[] args) { SpringApplication.run(OrderServerApplication.class, args); }}

完成上述操作後,從工程邏輯上看就已經完成了ShardingJdbc與Spring Boot應用的集成。接下來我們要做的就是根據規劃的分庫分表規則,通過配置文件進行分庫分表規則的配置,具體如下:

配置真實數據源spring.shardingsphere.datasource.names=ds0,ds1 配置第2個數據源spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.ds1.url=jdbc:mysql://127.0.0.1:3306/order_1?characterEncoding=utf-8spring.shardingsphere.datasource.ds1.username=rootspring.shardingsphere.datasource.ds1.password=123456 配置t_order表分庫策略(inline-基於行表達式的分片算法)spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_idspring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=ds${user_id % 2}如其他表有分庫分表需求,配置同上述t_order表FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: 34;orderId&34;tradeType&34;topup&34;amount&34;currency&34;cny&34;userId&FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: FCFAF2; --tt-darkmode-bgcolor: #C0BEB8;">覺得寫的還不錯的就點個讚,加個關注唄!點關注,不迷路,持續更新!!!

相關焦點

  • ShardingJdbc分庫分表實戰案例解析(下)
    《ShardingJdbc分庫分表實戰案例解析(上)》中我們初步介紹了使用ShardingJdbc實現訂單數據分散存儲的分庫分表方法,在本篇文章中將重點介紹在不停服的情況下實現數據分片存儲的在線擴容具體將以如下兩個常見的場景進行演示:1)、尚未進行分庫分表的單庫單表系統如何平穩的實施分庫分表方案;2)、已經實施過分庫分表方案的系統,由於數據量的持續增長導致原有分庫分表不夠用了
  • Sharding-jdbc的實戰入門之水平分表(一)
    分庫分表經驗值mysql單表經驗300W Mysql 可以輕鬆抗住600W 數據開始卡,優化可以解決(表結構,索引設計)800W ~ 1000W 牛逼的DBA 優化都會遇到瓶頸一般MySQL單表1000W
  • sharding-jdbc 分庫分表的 4種分片策略
    上文《快速入門分庫分表中間件 Sharding-JDBC (必修課)》中介紹了 ,另一部分未做分庫分表的表怎麼處理?、分表邏輯。# 分表策略# 分表分片健spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id# 分表算法spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name
  • SpringBoot+Sharding-JDBC操作分庫分表
    上面講述了使用Sharding-JDBC如何對水平分表的操作,接下來玩玩水平分庫分表操作。&分庫分表利器 文章中了解到什麼是垂直分庫分表、水平分庫分表,為什麼分庫分表;在咱們實際項目中,垂直分庫後會有多個資料庫,每個資料庫中有屬於自己的表和公共表(操作公共表在本節後面會講述)。
  • ShardingJDBC實現多資料庫節點分庫分表
    可能有以下幾種方案:分資料庫節點和分庫分表,將數據按照一定的規則均衡的分布到不同的資料庫節點,在一個資料庫節點上進行分庫,同時在一個資料庫中再次按照一定的規則進行分表,整個結構看起來就是一個樹狀結構;進行讀寫分離,將數據的寫入和查詢操作分散到不同的資料庫節點和資料庫上;採用
  • 分庫分表中間件 Sharding-JDBC
    ,大多是以水平切分模式(水平分庫、分表)為基礎來說的,數據分片將原本一張數據量較大的表 t_order 拆分生成數個表結構完全一致的小數據量表 t_orderSQL解析過程分為詞法解析和語法解析兩步,比如下邊這條查詢用戶訂單的SQL,先用詞法解析將SQL拆解成不可再分的原子單元。
  • 數據量巨大還不分庫分表?JDBC 入門與項目實戰
    因此想藉助一些分庫分表的中間件,實現自動化分庫分表實現。調研下來,發現Sharding-jdbc目前成熟度最高並且應用最廣的Java分庫分表的客戶端組件。邏輯表水平拆分的資料庫(表)的相同邏輯和數據結構表的總稱。例:訂單數據根據主鍵尾數拆分為10張表,分別是t_order_0到t_order_9,他們的邏輯表名為t_order。
  • Sharding-Jdbc之水平分庫和讀寫分離(二)
    在做分庫分表時,首先要定義好我們的分片規則,從業務邏輯上面要思路清晰。我們基於上一篇文章的案例,繼續進行分庫:為了提升程序的性能,除了在表欄位建立索引(如主鍵索引、唯一索引、普通索引等)、優化程序代碼以及 SQL 語句等常規手段外,利用資料庫主從讀寫分離(Master/Slave)架構:就是為了緩解資料庫壓力,將寫入和讀取操作分離為不同數據源,寫庫稱為主庫,讀庫稱為從庫,一主庫可配置多從庫。
  • SpringBoot 分庫分表sharding-sphere
    Apache ShardingSphere 是一套開源的分布式資料庫中間件解決方案組成的生態圈,它由 JDBC、Proxy 和 Sidecar(規劃中)這 3 款相互獨立,卻又能夠混合部署配合使用的產品組成。 它們均提供標準化的數據分片、分布式事務和資料庫治理功能,可適用於如 Java 同構、異構語言、雲原生等各種多樣化的應用場景。
  • 聊聊sharding jdbc
    水平分表就是將一張表的數據根據規則分散到多張表中,這樣降低單表的數據量,和水平分庫類似。實際應用中在系統設計之初,就應該考慮根據業務進行垂直分庫,垂直分表,而在後期當單表數據量過大時才考慮是否需要水平分庫分表,儘量通過其他方式來解決這種單表數據量過大的問題,比如緩存,冷熱數據分離等等,因為如果使用分庫分表將會給業務系統引入很多新的問題,提高了系統的複雜度。分庫分表後會帶來哪些問題?
  • 分布式秒殺實戰之千萬訂單流量數據分庫分表
    前言一般來說電商的日訂單都是百千萬級甚至是億萬級別的了,小小的資料庫肯定是撐不住的,這時候就要提前考慮分庫分表了。手動分表這個在秒殺一中已有體現,這裡僅僅是分表而已,提供一種思路,供參考,測試的時候自行建表。按照用戶 ID 來做 hash 分散訂單數據。為了減少遷移的數據量,一般擴容是以倍數的形式增加。比如原來是8個庫,擴容的時候,就要增加到16個庫,再次擴容,就增加到32個庫。這樣遷移的數據量,就小很多了。
  • mysql資料庫優化方案之分庫分表,輕鬆解決億級數據問題
    這次圍繞上次分庫分表,繼續說下shardingShpere是如何做到的代碼層面是如何實現的。分庫分表寫入的都是邏輯表,很多語句都是要進行改寫的。 mysql資料庫優化方案之分庫分表,輕鬆解決億級數據問題(七)SQL解析1.資料庫類型dbType;2.分庫分表規則shardingRule;3.詞法分析器引擎
  • 分庫分表核心概念
    什麼是分庫分表其實 分庫 和 分表 是兩個概念,只不過通常分庫與分表的操作會同時進行,以至於我們習慣性的將它們合在一起叫做分庫分表。分庫分表是為了解決由於庫、表數據量過大,而導致資料庫性能持續下降的問題。
  • SpringBoot分庫分表sharding-sphere2
    接著上一篇:上一篇的自定義分片算法有個錯誤DateShardingAlgorithm.java該類的日期轉換錯誤,正確如下:package com.pack.sharding.algorithm;import java.time.ZoneId;import java.time.format.DateTimeFormatter
  • 面試過關斬將:分庫分表-sharding-jdbc分頁,排序,條件查詢優化
    之前講了利用sharding-jdbc 3.1進行分表的情況,也講了利用一致性hash去做分表的高可用。今天講下分表後的分頁,排序,條件查詢優化。其實本身sharding-jdbc是提供了分頁功能的,我們方便期間是可以直接用的,但是不推薦用它。
  • SpringBoot整合Sharding-JDBC實現數據分表+讀寫分離
    此時如圖所示:案例詳解和上一篇文章使用的資料庫是同一個資料庫,資料庫信息如下:在主庫初始化Mysql數據的腳本,初始化完後,從庫也會創建這些表,腳本信息如下:本案例還是在上一篇文章的案例基礎之上進行改造,工程的目錄和pom的依賴見上一篇文章或者源碼。
  • 輕量級的資料庫中間件解決了SpringBoot中分庫分表問題
    官方文檔地址:https://shardingsphere.apache.org/document/current/cn/overview/本文demo實現了分庫分表功能。DDL語句如下 數據源 db0,db1,db2sharding.jdbc.datasource.names=db0,db1,db2 第二個資料庫sharding.jdbc.datasource.db1.type=com.zaxxer.hikari.HikariDataSourcesharding.jdbc.datasource.db1.driver-class-name
  • 淺談分庫分表
    分庫分表是處理高並發的常用手段,也是研發同學做系統設計時的常用選擇,接下來我通過理論和自己的實踐來聊一下對分庫分表的理解。我們通過如下幾個方面來談談。為什麼需要分庫分表分庫分表的方式讀寫分離為什麼要分庫分表?
  • 分庫分表需要考慮的問題及方案
    分庫分表的基本思想Sharding的基本思想就要把一個資料庫切分成多個部分放到不同的資料庫(server)上,從而緩解單一資料庫的性能問題。不太嚴格的講,對於海量數據的資料庫,如果是因為表多而數據多,這時候適合使用垂直切分,即把關係緊密(比如同一模塊)的表切分出來放在一個server上。
  • 一文快速入門分庫分表(必修課)
    我在網上陸陸續續的也看了一些有關於分庫分表的文章,可發現網上同質化的資料有點多,而且知識點又都比較零碎,還沒有詳細的實戰案例。為了更深入的學習下,我在某些平臺買了點付費課程,看了幾節課發現有點經驗的人看還可以,但對於新手入門來說,其實學習難度還是蠻大的。