SpringBoot3分庫分表

来源:https://www.cnblogs.com/cicada-smile/archive/2023/08/11/17622090.html
-Advertisement-
Play Games

按照業務拆分的方式稱為垂直分片,又稱為縱向拆分,它的核心理念是專庫專用;水平分片又稱為橫向拆分,是通過某些欄位根據某種規則將數據分散至多個庫或表中。 ...


標簽:ShardingSphere5.分庫.分表;

一、簡介

分庫分表的設計和實現方式,在之前的內容中總結過很多,本文基於SpringBoot3ShardingSphere5框架實現數據分庫分表的能力;

不得不提ShardingSphere5文檔中描述的兩個基本概念:

垂直分片

按照業務拆分的方式稱為垂直分片,又稱為縱向拆分,它的核心理念是專庫專用。在拆分之前,一個資料庫由多個數據表構成,每個表對應著不同的業務。而拆分之後,則是按照業務將表進行歸類,分佈到不同的資料庫中,從而將壓力分散至不同的資料庫。

水平分片

水平分片又稱為橫向拆分。 相對於垂直分片,它不再將數據根據業務邏輯分類,而是通過某個欄位(或某幾個欄位),根據某種規則將數據分散至多個庫或表中,每個分片僅包含數據的一部分。

下麵從案例實踐中,看看ShardingSphere5框架是如何實現分庫分表的原理;

二、工程搭建

1、工程結構

2、依賴管理

這裡只看兩個核心組件的依賴:shardingsphere-jdbc組件是5.2.1版本,mybatis組件是3.5.13版本,在依賴管理中還涉及MySQL和分頁等,並且需要添加很多排除配置,具體見源碼;

<!-- Mybatis組件 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>${mybatis.version}</version>
</dependency>

<!-- ShardingSphere分庫分表 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>

三、配置詳解

1、配置文件

此處只展示分庫分表的相關配值,預設數據源使用db_master庫,註意tb_order庫表路由的策略和分片演算法的關聯關係,其他工程配置詳見源碼倉庫;

spring:
  # 分庫分表配置
  shardingsphere:
    datasource:
      # 預設數據源
      sharding:
        default-data-source-name: db_master
      names: db_master,db_0,db_1
      db_master:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/shard_db
        username: root
        password: 123456
      db_0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/shard_db_0
        username: root
        password: 123456
      db_1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/shard_db_1
        username: root
        password: 123456
    rules:
      sharding:
        tables:
          # tb_order邏輯
          tb_order:
            actual-data-nodes: db_${0..1}.tb_order_${0..2}
            # tb_order庫路由
            database-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: database_inline
            # tb_order表路由
            table-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: table_inline
        sharding-algorithms:
          # tb_order庫路由演算法
          database_inline:
            type: INLINE
            props:
              algorithm-expression: db_${order_id % 2}
          # tb_order表路由演算法
          table_inline:
            type: INLINE
            props:
              algorithm-expression: tb_order_${order_id % 3}
    props:
      sql-show: true
      sql-comment-parse-enabled: true

2、配置原理

在配置中需要管理三個數據源,shard_db預設庫,在操作不涉及需要路由的表時預設使用該數據源,shard_db_0shard_db_1tb_order邏輯表的路由庫;

邏輯表tb_order整體使用兩個資料庫,每個庫建3張結構相同相同的表,在操作tb_order數據時,會根據order_id欄位值定位數據所屬的分片節點;

  • 庫路由db_${0..1}採用db_${order_id%2}的演算法;
  • 表路由tb_order_${0..2}採用tb_order_${order_id%3}的演算法;

四、測試案例

1、主庫操作

基於Mybatis持久層框架,實現對shard_db預設庫的數據操作,註意控制台的日誌列印,可以看到一系列解析邏輯以及庫表節點的定位,分頁查詢使用PageHelper組件即可;

public class MasterTest {
    @Autowired
    private BuyerMapper buyerMapper ;
    @Autowired
    private SellerMapper sellerMapper ;
    @Test
    public void testBuyerQuery (){
        // 主鍵查詢
        Buyer buyer = buyerMapper.selectByPrimaryKey(1) ;
        System.out.println(buyer.getId()+";"+buyer.getBuyerName());
    }
    @Test
    public void testBuyerInsert (){
        // 新增數據
        Buyer buyer = new Buyer() ;
        buyer.setBuyerName("買家Three");
        System.out.println(buyerMapper.insert(buyer));
    }
    @Test
    public void testBuyerUpdate (){
        // 更新數據
        Buyer buyer = buyerMapper.selectByPrimaryKey(3) ;
        if (buyer != null){
            buyer.setBuyerName("Three買家");
            System.out.println(buyerMapper.updateByPrimaryKey(buyer));
        }
    }
    @Test
    public void testSellerPage (){
        // 1、設置分頁和查詢條件
        PageHelper.startPage(2,2) ;
        SellerExample sellerExample = new SellerExample() ;
        sellerExample.setOrderByClause("id asc");
        // 2、查詢數據
        List<Seller> sellerList = sellerMapper.selectByExample(sellerExample) ;
        // 3、構建分頁實體對象
        PageInfo<Seller> pageInfo = new PageInfo<>(sellerList) ;
        System.out.println(pageInfo);
    }
}

2、分庫操作

在對tb_order表執行增刪改查時,會根據order_id的欄位值計算庫表的路由節點,註意分頁時會查詢所有的分庫和分表,然後彙總查詢的結果;

public class ShardTest {
    @Autowired
    private OrderMapper orderMapper ;
    /**
     * 寫入100條數據
     */
    @Test
    public void testOrderInsert (){
        for (int i=1 ; i<= 100 ; i++){
            Order order = new Order(i,i%3+1,i%3+1) ;
            // orderMapper.insert(order) ;
        }
    }
    @Test
    public void testOrderQuery (){
        Order order = orderMapper.selectByPrimaryKey(5) ;
        System.out.println(order);
    }
    @Test
    public void testOrderUpdate (){
        Order order = orderMapper.selectByPrimaryKey(100) ;
        if (order != null){
            // 原數據:買家和賣家ID都是2
            order.setBuyerId(1);
            order.setSellerId(3);
            orderMapper.updateByPrimaryKey(order) ;
        }
    }

    @Test
    public void testOrderPage (){
        // 1、設置分頁和查詢條件
        PageHelper.startPage(1,10) ;
        OrderExample orderExample = new OrderExample() ;
        orderExample.createCriteria().andBuyerIdEqualTo(2).andSellerIdEqualTo(2);
        orderExample.setOrderByClause("order_id desc");
        // 2、查詢數據
        List<Order> orderList = orderMapper.selectByExample(orderExample) ;
        // 3、構建分頁實體對象
        PageInfo<Order> pageInfo = new PageInfo<>(orderList) ;
        System.out.println(pageInfo);
    }
}

3、綜合查詢

編寫一個訂單詳情查詢介面,同時使用三個庫構建數據結構;如果是基於列表數據的檢索,比較常規做法的是構建ES索引結構,如果沒有搜索的需求,可以在訂單表分頁查詢後去拼接其他結構;

@RestController
public class OrderController {

    @Resource
    private BuyerMapper buyerMapper ;
    @Resource
    private SellerMapper sellerMapper ;
    @Resource
    private OrderMapper orderMapper ;

    /**
     * 查詢訂單詳情
     */
    @GetMapping("/order/info/{orderId}")
    public Map<String,Object> orderInfo (@PathVariable Integer orderId){
        Map<String,Object> orderMap = new HashMap<>() ;
        Order order = orderMapper.selectByPrimaryKey(orderId) ;
        if (order != null){
            orderMap.put("order",order) ;
            orderMap.put("buyer",buyerMapper.selectByPrimaryKey(order.getBuyerId())) ;
            orderMap.put("seller",sellerMapper.selectByPrimaryKey(order.getSellerId())) ;
        }
        return orderMap ;
    }
}

查看SQL語句

db_master ::: select id, buyer_name from tb_buyer where id = ? ::: [1]
db_master ::: select id, seller_name from tb_seller where id = ? ::: [3]
db_0 ::: select order_id, seller_id, buyer_id from tb_order_1 where order_id = ? ::: [100]

五、參考源碼

文檔倉庫:
https://gitee.com/cicadasmile/butte-java-note

源碼倉庫:
https://gitee.com/cicadasmile/butte-spring-parent
Gitee主頁: https://gitee.com/cicadasmile/butte-java-note
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 具體報錯為: Error attempting to get column 'DISEASENAME' from result set. Cause: java.sql.SQLFeatureNotSupportedException: 這個 org.postgresql.jdbc.PgResultS ...
  • 來源:blog.csdn.net/zjhred/article/details/84976734 在文章的開頭,先說下NPE問題,NPE問題就是,我們在開發中經常碰到的NullPointerException。假設我們有兩個類,他們的UML類圖如下圖所示 ![](https://img2023.cn ...
  • HotSpot的演算法實現 HotSpot的演算法實現概要 1、枚舉根節點 由於目前的主流Java虛擬機使用的都是準確式GC(這個概念在第1章介紹Exact VM對Classic VM的改進時講過),所以當執行系統停頓下來後,並不需要一個不漏地檢查完所有執行上下文和全局的引用位置,虛擬機應當是有辦法直接 ...
  • 問題:在Windows環境下部署java的jar包,若有多個服務同時啟動,很難找到相應服務重啟。每次都重啟全部服務很麻煩。應用場景大多用於部署測試。 適用:jar部署,war部署不適用。 解決方案:找到相應jar服務關閉並重啟。 註意: 1、正確設置埠,jar服務運行的埠; 2、正確設置jar文 ...
  • 數據類型是編程語言中的一個重要概念,它定義了數據的類型和提供了特定的操作和方法。在 python 中,數據類型的作用是將不同類型的數據進行分類和定義,例如數字、字元串、列表、元組、集合、字典等。這些數據類型不僅定義了數據的類型,還為數據提供了一些特定的操作和方法,例如字元串支持連接和分割,列表支持排... ...
  • ## 依賴導入 ```xml org.hibernate.orm hibernate-core 6.2.7.Final com.mysql mysql-connector-j 8.0.33 ``` ## 配置文件 ```xml com.mysql.cj.jdbc.Driver jdbc:mysql: ...
  • 在實際開發過程中,我們可能會遇到併發寫文件的場景,如果處理不當很可能出現文件內容亂序問題。下麵我們通過一個示常式序描述這一過程並給出解決該問題的方法。 ...
  • # 前言 在面試這一篇我們介紹過[CountDownLatch和CyclicBarrier](https://github.com/jmilktea/jtea/blob/master/%E9%9D%A2%E8%AF%95/CountDownLatch%E5%92%8CCyclicBarrier.md ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...