自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

分庫分表如何管理不同實(shí)例中幾萬張分片表?

數(shù)據(jù)庫 其他數(shù)據(jù)庫
在使用ShardingSphere?實(shí)現(xiàn)分庫分表的時(shí)候,要摒棄先建表、再配規(guī)則的傳統(tǒng)思維,要先確定規(guī)則在建表,管理表是一件很簡單的事,我們只要告訴ShardingSphere分片數(shù)量和分布規(guī)則,剩下的就讓框架來處理就好了。

ShardingSphere實(shí)現(xiàn)分庫分表,如何管理分布在不同數(shù)據(jù)庫實(shí)例中的成千上萬張分片表?

上邊的問題是之前有個(gè)小伙伴看了我的分庫分表的文章,私下咨詢我的,看到他的提問我第一感覺就是這老鐵沒用過ShardingSphere,因?yàn)檫@個(gè)問題在ShardingSphere中已經(jīng)有了很好的解決方案,接下來看看怎么實(shí)現(xiàn)。

本文案例代碼GitHub地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/shardingsphere101/shardingsphere-autocreate-table

圖片圖片

ShardingSphere學(xué)習(xí)路線

本文是《ShardingSphere5.x分庫分表原理與實(shí)戰(zhàn)》系列的第四篇文章,在進(jìn)行分庫分表設(shè)計(jì)時(shí),確認(rèn)好了數(shù)據(jù)節(jié)點(diǎn)數(shù)量和分片策略以后,接下來要做的就是管理大量的分片表。實(shí)際實(shí)施過程中可能存在上百個(gè)分片數(shù)據(jù)庫實(shí)例,每個(gè)實(shí)例中都可能有成千上萬個(gè)分片表,如果僅依靠人力來完成這些任務(wù)顯然是不現(xiàn)實(shí)的。所以,想要快速且自動(dòng)化管理這些分片表,使用工具是十分必要滴。

前言

ShardingSphere框架成員中的Shardingsphere-jdbc和Shardingsphere-proxy都提供了自動(dòng)化管理分片表的功能auto-tables,可以統(tǒng)一維護(hù)大量的分片表,避免了手動(dòng)編寫腳本和維護(hù)分片表的繁瑣工作,極大程度減少分庫分表的開發(fā)和維護(hù)成本,提升效率和可靠性。

圖片圖片

這里咱們先使用Shardingsphere-jdbc來實(shí)際操作一下,Shardingsphere-proxy方式后續(xù)會(huì)有單獨(dú)的文章詳細(xì)講解,就不在這里展開了。

準(zhǔn)備工作

假設(shè)我們要對(duì)t_order表進(jìn)行分庫分表,首先我們要做的就是確定好分片方案,這里使用兩個(gè)數(shù)據(jù)庫實(shí)例db0、db1,每個(gè)實(shí)例中t_order表分成1000張分片表t_order_1 ~ t_order_1000,order_id字段作為分片鍵,分片算法使用取模算法order_id % n,分布式主鍵生成策略采用snowflake。

t_order邏輯表的表結(jié)構(gòu)如下:

CREATE TABLE `t_order` (
 `order_id` BIGINT ( 20 ) NOT NULL COMMENT "訂單表分布式主健ID",
 `order_number` VARCHAR ( 255 ) NOT NULL COMMENT "訂單號(hào)",
 `customer_id` BIGINT ( 20 ) NOT NULL COMMENT "用戶ID",
 `order_date` date NOT NULL COMMENT "下單時(shí)間",
 `total_amount` DECIMAL ( 10, 2 ) NOT NULL COMMENT "訂單金額",
    PRIMARY KEY ( `order_id` ) USING BTREE 
);

有了這些基礎(chǔ)信息,可以先來進(jìn)行t_order表的分片配置了,不考慮其他因素,這里先Run起來!

分片規(guī)則配置

設(shè)定好分片規(guī)則,接著編寫邏輯表t_order的分片規(guī)則的配置,我分別使用yml配置和Java編碼兩種方式做了實(shí)現(xiàn)。要注意的是兩種方式不要并存,不然啟動(dòng)會(huì)報(bào)錯(cuò)。

yml配置方式

使用yml配置相對(duì)簡單易用比較直觀,適合對(duì)分庫分表要求不太復(fù)雜的場(chǎng)景,完整配置如下:

spring:
  shardingsphere:
    datasource:
      # 數(shù)據(jù)源名稱,多數(shù)據(jù)源以逗號(hào)分隔 ,放在第一個(gè)的數(shù)據(jù)源為未配置分片規(guī)則表的默認(rèn)數(shù)據(jù)源
      names: db0 , db1
      # 名稱與上邊 names 保持一致
      db0:
      ....

      db1:
      ....
    # 具體規(guī)則配置
    rules:
      sharding:
        # 分片算法定義
        sharding-algorithms:
          # 自定義分片算法名稱
          t_order_database_algorithms:
            # 分片算法類型
            type: INLINE
            # 自定義參數(shù)
            props:
              algorithm-expression: db$->{order_id % 2}
          t_order_table_algorithms:
            type: INLINE
            props:
              algorithm-expression: t_order_$->{order_id % 1000}
          t_order_mod:
            type: MOD
            props:
              # 指定分片數(shù)量
              sharding-count: 1000
        # 分布式序列算法配置
        key-generators:
          t_order_snowflake:
            type: SNOWFLAKE
            # 分布式序列算法屬性配置
            props:
              worker-id: 1
        tables:
          # 邏輯表名稱
          t_order:
            # 數(shù)據(jù)節(jié)點(diǎn):數(shù)據(jù)庫.分片表
            actual-data-nodes: db$->{0..1}.t_order_$->{1..1000}
            # 分庫策略
            database-strategy:
              standard:
                # 分片列名稱
                sharding-column: order_id
                # 分片算法名稱
                sharding-algorithm-name: t_order_database_algorithms
            # 分表策略
            table-strategy:
              standard:
                # 分片列名稱
                sharding-column: order_id
                # 分片算法名稱
                sharding-algorithm-name: t_order_table_algorithms
            # 主鍵生成策略
            keyGenerateStrategy:
              column: order_id
              keyGeneratorName: t_order_snowflake
    # 屬性配置
    props:
      # 展示修改以后的sql語句
      sql-show: true

Java編碼方式

使用Java編碼方式更加靈活和可擴(kuò)展,可以根據(jù)業(yè)務(wù)定制分片規(guī)則,適合對(duì)分庫分表有特殊需求或需要?jiǎng)討B(tài)調(diào)整的場(chǎng)景。

/**
 * 公眾號(hào):程序員小富
 */
@Configuration
public class ShardingConfiguration {

    /**
     * 配置分片數(shù)據(jù)源
     * 公眾號(hào):程序員小富
     */
    @Bean
    public DataSource getShardingDataSource() throws SQLException {
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put("db0", dataSource0());
        dataSourceMap.put("db1", dataSource1());

        // 分片rules規(guī)則配置
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();

        // 分片算法
        shardingRuleConfig.setShardingAlgorithms(getShardingAlgorithms());
        // 配置 t_order 表分片規(guī)則
        ShardingTableRuleConfiguration orderTableRuleConfig = new ShardingTableRuleConfiguration("t_order", "db${0..1}.t_order_${1..1000}");
        orderTableRuleConfig.setTableShardingStrategy(new StandardShardingStrategyConfiguration("order_id", "t_order_table_algorithms"));
        orderTableRuleConfig.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("order_id", "t_order_database_algorithms"));
        shardingRuleConfig.getTables().add(orderTableRuleConfig);

        // 是否在控制臺(tái)輸出解析改造后真實(shí)執(zhí)行的 SQL
        Properties properties = new Properties();
        properties.setProperty("sql-show", "true");

        // 創(chuàng)建 ShardingSphere 數(shù)據(jù)源
        return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfig), properties);
    }

    /**
     * 配置數(shù)據(jù)源1
     * 公眾號(hào):程序員小富
     */
    public DataSource dataSource0() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/db0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimeznotallow=Asia/Shanghai&allowPublicKeyRetrieval=true");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        return dataSource;
    }

    /**
     * 配置數(shù)據(jù)源2
     * 公眾號(hào):程序員小富
     */
    public DataSource dataSource1() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimeznotallow=Asia/Shanghai&allowPublicKeyRetrieval=true");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        return dataSource;
    }

    /**
     * 配置分片算法
     * 公眾號(hào):程序員小富
     */
    private Map<String, AlgorithmConfiguration> getShardingAlgorithms() {
        Map<String, AlgorithmConfiguration> shardingAlgorithms = new LinkedHashMap<>();

        // 自定義分庫算法
        Properties databaseAlgorithms = new Properties();
        databaseAlgorithms.setProperty("algorithm-expression", "db$->{order_id % 2}");
        shardingAlgorithms.put("t_order_database_algorithms", new AlgorithmConfiguration("INLINE", databaseAlgorithms));

        // 自定義分表算法
        Properties tableAlgorithms = new Properties();
        tableAlgorithms.setProperty("algorithm-expression", "db$->{order_id % 1000}");
        shardingAlgorithms.put("t_order_table_algorithms", new AlgorithmConfiguration("INLINE", tableAlgorithms));

        return shardingAlgorithms;
    }
}

上面我們?cè)趹?yīng)用中編寫好了分片規(guī)則,現(xiàn)在就差在數(shù)據(jù)庫實(shí)例中創(chuàng)建分片表了,手動(dòng)創(chuàng)建和管理1000張分片表確實(shí)是一個(gè)又臟又累的活,反正我是不會(huì)干的!

管理分片表

其實(shí),ShardingSphere內(nèi)已經(jīng)為我們提供了管理分片表的能力。

當(dāng)一張邏輯表t_order被配置了分片規(guī)則,那么接下來對(duì)邏輯表的各種DDL操作(例如創(chuàng)建表、修改表結(jié)構(gòu)等),命令和數(shù)據(jù)會(huì)根據(jù)分片規(guī)則,執(zhí)行和存儲(chǔ)到每個(gè)分片數(shù)據(jù)庫和分片庫中的相應(yīng)分片表中,以此保持整個(gè)分片環(huán)境的一致性。

不過,使用Shardingsphere-jdbc管理分片表的過程中,是需要我們手動(dòng)編寫對(duì)邏輯表的DDL操作的代碼。我們來跑幾個(gè)單元測(cè)試用例來觀察實(shí)際的執(zhí)行效果,直接使用jdbcTemplate執(zhí)行創(chuàng)建邏輯表t_order的SQL。

/**
 * @author 公眾號(hào):程序員小富
 * 自動(dòng)創(chuàng)建分片表
 * @date 2023/12/31 17:25
 */
@SpringBootTest
class AutoCreateTablesTests {
    @Resource
    private JdbcTemplate jdbcTemplate;
    /**
     * 執(zhí)行創(chuàng)建邏輯表的SQL,會(huì)根據(jù)AutoTables的配置自動(dòng)在對(duì)應(yīng)的數(shù)據(jù)源內(nèi)創(chuàng)建分片表
     * @author 公眾號(hào):程序員小富
     */
    @Test
    public void autoCreateOrderTableTest() {

        jdbcTemplate.execute("CREATE TABLE `t_order` (\n" +
                "  `order_id` bigint(20) NOT NULL,\n" +
                "  `order_number` varchar(255) NOT NULL,\n" +
                "  `customer_id` bigint(20) NOT NULL,\n" +
                "  `order_date` date NOT NULL,\n" +
                "  `total_amount` decimal(10,2) NOT NULL,\n" +
                "  PRIMARY KEY (`order_id`) USING BTREE\n" +
                ");");
    }
}

根據(jù)之前配置的分片規(guī)則,將會(huì)在兩個(gè)數(shù)據(jù)庫實(shí)例 db0 和 db1 中,分別生成1000張命名為t_order_1到t_order_1000的分片表,看到兩個(gè)數(shù)據(jù)庫均成功創(chuàng)建了1000張分片表。

圖片圖片

在次執(zhí)行更新t_order表SQL,將字段order_number長度從 varchar(255)擴(kuò)展到 varchar(500),執(zhí)行SQL看下效果。

/**
 * @author 公眾號(hào):程序員小富
 * 自動(dòng)創(chuàng)建分片表
 * @date 2023/12/31 17:25
 */
@SpringBootTest
class AutoCreateTablesTests {
    @Resource
    private JdbcTemplate jdbcTemplate;
    
    @Test
    public void autoModifyOrderTableTest() {

        jdbcTemplate.execute("ALTER TABLE t_order MODIFY COLUMN order_number varchar(500);");
    }
}

通過查看兩個(gè)分片庫,我們成功地將所有分片表的order_number字段長度更改為了varchar(500),在控制臺(tái)日志中,可以看到它是通過在每個(gè)分片庫內(nèi)依次執(zhí)行了1000次命令實(shí)現(xiàn)的。

圖片圖片

Shardingsphere-jdbc實(shí)現(xiàn)分庫分表時(shí),可以采用這種默認(rèn)的方式來管理分片表。但要注意的是,由于涉及到不同的數(shù)據(jù)庫實(shí)例,如果不使用第三方的分布式事務(wù)管理工具(例如Seata等),執(zhí)行過程是無法保證事務(wù)一致性的。

自定義管理分片表

上邊為邏輯表配置分片規(guī)則,應(yīng)用程序內(nèi)執(zhí)行對(duì)邏輯表的DDL操作,就可以很輕松的管理分片表。

自定義

不過,默認(rèn)的分片管理還是有局限性的,我們?cè)谠O(shè)計(jì)分片規(guī)則時(shí)往往會(huì)根據(jù)不同的業(yè)務(wù)維度來劃分,例如按天、月、按季度生成分片表并分布到不同數(shù)據(jù)源中等。這樣就需要一些自定義的規(guī)則來實(shí)現(xiàn)。

ShardingSphere 5.X版本后推出了一種新的管理分片配置方式:AutoTable。設(shè)置了AutoTable的邏輯表,將交由ShardingSphere自動(dòng)管理分片,用戶只需要指定分片數(shù)量和使用的數(shù)據(jù)庫實(shí)例,無需再關(guān)心表的具體分布,配置格式如下:

spring:
  shardingsphere:
    # 數(shù)據(jù)源配置
    datasource:
      ......
    # 具體規(guī)則配置
    rules:
      sharding:
        # 邏輯表分片規(guī)則
        tables:
          # 邏輯表名稱
          t_order:
            .....
        # 自動(dòng)分片表規(guī)則配置
        auto-tables:
          t_order: # 邏輯表名稱
            actual-data-sources: db$->{0..1}
            sharding-strategy: # 切分策略
              standard: # 用于單分片鍵的標(biāo)準(zhǔn)分片場(chǎng)景
                sharding-column: order_id # 分片列名稱
                sharding-algorithm-name: t_order_mod # 自動(dòng)分片算法名稱

ShardingSphere-Jdbc中配置使用auto-tables主要兩個(gè)參數(shù),actual-data-sources指定數(shù)據(jù)源分布,由于是管理分片表所以只需數(shù)據(jù)源信息即可;sharding-strategy指具體采用何種算法來進(jìn)行分片。

對(duì)邏輯表的DDL操作,系統(tǒng)會(huì)首先檢查是否配置了AutoTable,如果已配置,則優(yōu)先采用配置的規(guī)則;若未配置,則將使用默認(rèn)的邏輯表分片規(guī)則。

AutoTable支持ShardingSphere內(nèi)置的全部自動(dòng)分片算法,所謂自動(dòng)分片算法就是根據(jù)actualDataSources設(shè)置的數(shù)據(jù)源信息,使用對(duì)應(yīng)內(nèi)置算法自行解析處理。

  • MOD:取模分片算法
  • HASH_MOD:哈希取模分片算法
  • VOLUME_RANGE:基于分片容量的范圍分片算法
  • BOUNDARY_RANGE:基于分片邊界的范圍分片算法
  • AUTO_INTERVAL:自動(dòng)時(shí)間段分片算法

AutoTable使用

舉個(gè)例子,我們使用內(nèi)置MOD取模算法作為AutoTable的分片算法,同樣是db0、db1兩個(gè)實(shí)例中各創(chuàng)建1000張分片表。那么當(dāng)對(duì)邏輯表的DDL操作時(shí),ShardingSphere會(huì)依據(jù)分片表編號(hào)t_order_0~t_order_1999 % 數(shù)據(jù)庫實(shí)例數(shù)取模來確認(rèn)DDL命令路由到哪個(gè)實(shí)例中執(zhí)行。

spring:
  shardingsphere:
    # 數(shù)據(jù)源配置
    datasource:
      .....
    # 具體規(guī)則配置
    rules:
      sharding:
        # 自動(dòng)分片表規(guī)則配置
        auto-tables:
          t_order:
            actual-data-sources: db$->{0..1}
            sharding-strategy:
              standard:
                sharding-column: order_date
                sharding-algorithm-name: t_order_mod
        # 分片算法定義
        sharding-algorithms:
          t_order_mod:
            type: MOD
            props:
              # 指定分片數(shù)量
              sharding-count: 2000

還是執(zhí)行剛才創(chuàng)建表的單元測(cè)試,會(huì)發(fā)現(xiàn)db0、db1兩個(gè)實(shí)例中已經(jīng)各自創(chuàng)建了1000張分片表,但你會(huì)發(fā)現(xiàn)1000張表已經(jīng)不再是按照順序創(chuàng)建的了。

圖片圖片

上邊使用的是內(nèi)置自動(dòng)分片算法,它對(duì)于我們來說是黑盒,提供它方便我們拿來即用。不過,如果想要做到更細(xì)粒度的管理分片表,最好的辦法就是自定義分片算法,后續(xù)章節(jié)會(huì)介紹所有內(nèi)置分片算法和自定義分片算法的使用。

總結(jié)

在使用ShardingSphere實(shí)現(xiàn)分庫分表的時(shí)候,要摒棄先建表、再配規(guī)則的傳統(tǒng)思維,要先確定規(guī)則在建表,管理表是一件很簡單的事,我們只要告訴ShardingSphere分片數(shù)量和分布規(guī)則,剩下的就讓框架來處理就好了。

本文案例代碼GitHub地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/shardingsphere101/shardingsphere-autocreate-table

責(zé)任編輯:武曉燕 來源: 程序員小富
相關(guān)推薦

2024-06-26 00:34:12

2020-07-30 17:59:34

分庫分表SQL數(shù)據(jù)庫

2020-07-28 09:04:09

NewSQL分庫分表

2019-11-12 09:54:20

分庫分表數(shù)據(jù)

2022-07-11 08:16:47

NewSQL關(guān)系數(shù)據(jù)庫系統(tǒng)

2024-11-22 15:32:19

2020-11-18 09:39:02

MySQL數(shù)據(jù)庫SQL

2021-08-31 20:21:11

VitessMySQL分庫

2023-08-11 08:59:49

分庫分表數(shù)據(jù)數(shù)據(jù)庫

2018-03-14 09:49:35

數(shù)據(jù)庫遷移

2020-11-17 08:08:34

分庫分表

2024-07-26 00:16:11

2025-04-01 08:45:00

2021-01-26 05:37:08

分庫分表內(nèi)存

2021-05-20 07:32:59

分庫分表數(shù)據(jù)量

2024-04-01 08:53:50

分庫分表分片算法

2019-07-31 09:27:23

數(shù)據(jù)庫MySQLSQL

2024-01-03 08:14:33

GreatSQLMyCat庫名字

2024-02-21 12:17:00

2019-01-16 14:00:54

數(shù)據(jù)庫分庫分表
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)