欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ShardingSphere結(jié)合MySQL實(shí)現(xiàn)分庫分表的項(xiàng)目實(shí)踐

 更新時間:2024年03月14日 09:27:56   作者:nana_Wang123  
在實(shí)際開發(fā)中,如果表的數(shù)據(jù)過大我們需要把一張表拆分成多張表,本文主要介紹了使用ShardingSphere實(shí)現(xiàn)MySQL分庫分表,具有一定的參考價值,感興趣的可以了解一下

ShardingSphere介紹

Apache ShardingSphere 是一套開源的分布式數(shù)據(jù)庫中間件解決方案組成的生態(tài)圈,它由JDBC、Proxy和Sidecar(規(guī)劃中)這3款相互獨(dú)立,卻又能夠混合部署配合使用的產(chǎn)品組成。 它們均提供標(biāo)準(zhǔn)化的數(shù)據(jù)分片、分布式事務(wù)和數(shù)據(jù)庫治理功能,可適用于如 Java 同構(gòu)、異構(gòu)語言、云原生等各種多樣化的應(yīng)用場景。

  • 一套開源的分布式數(shù)據(jù)庫中間件解決方案
  • 有3個產(chǎn)品:JDBC、Proxy、Sidecar

分庫分表

當(dāng)我們使用讀寫分離、索引、緩存后,數(shù)據(jù)庫的壓力還是很大的時候,這就需要使用到數(shù)據(jù)庫拆分了。

  • 一般來說, MySQL推薦的單表數(shù)據(jù)量在500w ~ 800w, 超過800w則建議分表.
  • 或是在系統(tǒng)接口響應(yīng)時間明顯變慢, 并且通過代碼優(yōu)化, 改寫sql等形式無法獲得明顯提升, 且明確了性能瓶頸在數(shù)據(jù)庫時, 建議分表
  • 分庫則是在分表后單庫性能到達(dá)瓶頸后進(jìn)行, 如果個人或項(xiàng)目有錢任性的除外.分庫主要解決的是并發(fā)量大的問題。

垂直拆分

分表
表中的字段較多,一般將不常用的、 數(shù)據(jù)較大、長度較長的拆分到“擴(kuò)展表“。一般情況加表的字段可能有幾百列,此時是按照字段進(jìn)行數(shù)豎直切。注意垂直分是列多的情況。

分庫
一個數(shù)據(jù)庫的表太多。此時就會按照一定業(yè)務(wù)邏輯進(jìn)行垂直切,比如用戶相關(guān)的表放在一個數(shù)據(jù)庫里,訂單相關(guān)的表放在一個數(shù)據(jù)庫里。注意此時不同的數(shù)據(jù)庫應(yīng)該存放在不同的服務(wù)器上,此時磁盤空間、內(nèi)存、TPS等等都會得到解決。

優(yōu)點(diǎn):

  • 拆分后業(yè)務(wù)清晰,拆分規(guī)則明確。
  • 系統(tǒng)之間整合或擴(kuò)展容易。
  • 數(shù)據(jù)維護(hù)簡單。

缺點(diǎn):

  • 部分業(yè)務(wù)表無法 join,只能通過接口方式解決,提高了系統(tǒng)復(fù)雜度。
  • 受每種業(yè)務(wù)不同的限制存在單庫性能瓶頸,不易數(shù)據(jù)擴(kuò)展跟性能提高。
  • 事務(wù)處理復(fù)雜。

水平拆分

分表
單表的數(shù)據(jù)量太大。按照某種規(guī)則(RANGE,HASH取模等),切分到多張表里面去。 但是這些表還是在同一個庫中,所以庫級別的數(shù)據(jù)庫操作還是有IO瓶頸。這種情況是不建議使用的,因?yàn)閿?shù)據(jù)量是逐漸增加的,當(dāng)數(shù)據(jù)量增加到一定的程度還需要再進(jìn)行切分。比較麻煩。

分庫
水平分庫理論上切分起來是比較麻煩的,它是指將單張表的數(shù)據(jù)切分到多個服務(wù)器上去,每個服務(wù)器具有相應(yīng)的庫與表,只是表中數(shù)據(jù)集合不同。 水平分庫分表能夠有效的緩解單機(jī)和單庫的性能瓶頸和壓力,突破IO、連接數(shù)、硬件資源等的瓶頸。

優(yōu)點(diǎn):

  • 不存在單庫大數(shù)據(jù),高并發(fā)的性能瓶頸。
  • 對應(yīng)用透明,應(yīng)用端改造較少。
  • 按照合理拆分規(guī)則拆分,join 操作基本避免跨庫。
  • 提高了系統(tǒng)的穩(wěn)定性跟負(fù)載能力。

缺點(diǎn):

  • 拆分規(guī)則難以抽象。
  • 分片事務(wù)一致性難以解決。
  • 數(shù)據(jù)多次擴(kuò)展難度跟維護(hù)量極大。
  • 跨庫 join 性能較差。

分片后的常見問題

數(shù)據(jù)傾斜
這個幾乎是無法避免的, 即使是id取模, 也會因?yàn)閿?shù)據(jù)的刪除導(dǎo)致每張分表的數(shù)據(jù)不一樣, 或者id是UUID, 取模也會導(dǎo)致數(shù)據(jù)發(fā)生傾斜. 但是一般來說傾斜只要不是太離譜, 都在我們的接受范圍以內(nèi).

id生成策略
如果分片之前你的id是遞增的, 那么分片后你就無法保證id的全局唯一性, 這時比較常見的業(yè)內(nèi)方案就是UUID或者SnowFlake.
當(dāng)然如果想要排序和分頁, 就需要有個id生成器去統(tǒng)一集中生成連續(xù)的id(參考下文).

全路由
這個是最糟糕的情況, 這種情況會讓我們的查詢比分片之前還要慢, 可以在自定義的分片算法中校驗(yàn)這種情況直接拋出異常, 然后coder們根據(jù)日志中的報(bào)錯來統(tǒng)計(jì)這部分sql加以改寫.

jpa級聯(lián)
如果jpa級聯(lián)中包含分表, 則需要拆除這種級聯(lián)關(guān)系, 以免導(dǎo)致上述全路由情況發(fā)生.

排序&分頁
如果只是單獨(dú)分頁, Sharding Sphere會剔除數(shù)據(jù)不寫入內(nèi)存, 實(shí)際上不會導(dǎo)致內(nèi)存的大量占用, 但如果加上排序, 那情況就不容樂觀了, 官方建議通過可以保證連續(xù)性的id去加以限制.

四種分片算法&五種分片策略

4種分片算法

精確分片算法
對應(yīng)PreciseShardingAlgorithm,用于處理使用單一鍵作為分片鍵的=與IN進(jìn)行分片的場景。需要配合StandardShardingStrategy使用。

范圍分片算法
對應(yīng)RangeShardingAlgorithm,用于處理使用單一鍵作為分片鍵的BETWEEN AND、>、<、>=、<=進(jìn)行分片的場景。需要配合StandardShardingStrategy使用。

復(fù)合分片算法
對應(yīng)ComplexKeysShardingAlgorithm,用于處理使用多鍵作為分片鍵進(jìn)行分片的場景,包含多個分片鍵的邏輯較復(fù)雜,需要應(yīng)用開發(fā)者自行處理其中的復(fù)雜度。需要配合ComplexShardingStrategy使用。

Hint分片算法
對應(yīng)HintShardingAlgorithm,用于處理使用Hint行分片的場景。需要配合HintShardingStrategy使用。

5種分片策略

標(biāo)準(zhǔn)分片策略
對應(yīng)StandardShardingStrategy。提供對SQL語句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持單分片鍵,提供PreciseShardingAlgorithm和RangeShardingAlgorithm兩個分片算法。PreciseShardingAlgorithm是必選的,用于處理=和IN的分片。RangeShardingAlgorithm是可選的,用于處理BETWEEN AND, >, <, >=, <=分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND將按照全庫路由處理。

復(fù)合分片策略
對應(yīng)ComplexShardingStrategy。復(fù)合分片策略。提供對SQL語句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片鍵,由于多分片鍵之間的關(guān)系復(fù)雜,因此并未進(jìn)行過多的封裝,而是直接將分片鍵值組合以及分片操作符透傳至分片算法,完全由應(yīng)用開發(fā)者實(shí)現(xiàn),提供最大的靈活度。

行表達(dá)式分片策略
對應(yīng)InlineShardingStrategy。使用Groovy的表達(dá)式,提供對SQL語句中的=和IN的分片操作支持,只支持單分片鍵。對于簡單的分片算法,可以通過簡單的配置使用,從而避免繁瑣的Java代碼開發(fā),如: t_user_$->{u_id % 8} 表示t_user表根據(jù)u_id模8,而分成8張表,表名稱為t_user_0t_user_7

Hint分片策略
對應(yīng)HintShardingStrategy。通過Hint指定分片值而非從SQL中提取分片值的方式進(jìn)行分片的策略。

不分片策略
對應(yīng)NoneShardingStrategy。不分片的策略。

ShardingSphere-JDBC

定位為輕量級 Java 框架,在 Java 的 JDBC 層提供的額外服務(wù)。 它使用客戶端直連數(shù)據(jù)庫,以 jar 包形式提供服務(wù),無需額外部署和依賴,可理解為增強(qiáng)版的 JDBC 驅(qū)動,完全兼容 JDBC 和各種 ORM 框架。

需要注意的是,分庫分表并不是由 ShardingSphere-JDBC 來做,它是用來負(fù)責(zé)操作已經(jīng)分完之后的 CRUD 操作。

水平分表實(shí)操(單分片鍵,分片類型:HASH_MODE)

環(huán)境使用:SpringBoot 2.7.12 + MybatisPlus + ShardingSphere-jdbc 5.2.0 + Druid連接池

本示例為單庫,庫內(nèi)有6個分表,并且按照order_id的hash值進(jìn)行取模計(jì)算得到實(shí)際表

添加Maven依賴

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
</dependency>

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.1.0</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>

按照水平分表創(chuàng)建數(shù)據(jù)庫

CREATE TABLE `t_order_5`
(
    `order_id`    bigint NOT NULL AUTO_INCREMENT,
    `price`       double(12,2),
    `user_id`     int    NOT NULL,
    `address_id`  bigint NOT NULL,
    `city`        varchar(32) NULL DEFAULT NULL,
    `status`      tinyint NULL DEFAULT NULL,
    `interval_time` datetime NULL DEFAULT NULL,
    `creator`     varchar(32) NULL DEFAULT NULL,
    `create_time` datetime NULL DEFAULT NULL,
    `updater`     varchar(32) NULL DEFAULT NULL,
    `update_time` datetime NULL DEFAULT NULL,
    PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic

配置Sharding-jdbc分片策略

application.yml內(nèi)容:

spring:
  main:
    banner-mode: off

  shardingsphere:
    # 配置數(shù)據(jù)源,給數(shù)據(jù)源起別名ds
    datasource:
      ds:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234
      names: ds
    rules:
      sharding:
        binding-tables:
          - t_order,t_order_item
        broadcast-tables: t_address
        # 分片算法
        sharding-algorithms:
          t-order-algorithm:
            type: HASH_MOD
            props:
              sharding-count: '6'
          t-order-item-inline:
            type: INLINE
            props:
              algorithm-expression: t_order_item_$->{order_id % 2}
        tables:
        # 分表
          t_order:
            actual-data-nodes: ds.t_order_$->{0..5}   # 真實(shí)表名
            table-strategy:
              standard:
                sharding-algorithm-name: t-order-algorithm
                sharding-column: order_id   # 分片鍵
          t_order_item:
            actual-data-nodes: ds.t_order_item_$->{0..1}
            table-strategy:
              standard:
                sharding-algorithm-name: t-order-item-inline
                sharding-column: order_id
    props:
      sql-show: true



#mybatis-plus:
#  global-config:
#    banner: false
#    db-config:
#      id-type: assign_id  #使用雪花算法開啟數(shù)據(jù)入庫時ID自增
#      logic-delete-field: deleted
#      logic-delete-value: 1
#      logic-not-delete-value: 0
#  #開啟mp的日志(控制臺輸出)
#  configuration:
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

mybatis:
  mapper-locations: classpath*:/mappers/*-mapper.xml
  type-aliases-package: com.panliu.domain
  configuration:
    default-fetch-size: 20
    default-statement-timeout: 30
    map-underscore-to-camel-case: true
    use-generated-keys: true

測試代碼運(yùn)行

@Slf4j
@SpringBootTest
public class OrderMapperTests {
    private final static String[] CITIES = {"shanghai", "beijing"};
    /**
     * -120000, 0, 18, 20000, 40000, 50000, 60000, 64000, 80000, 99000
     */
    private final static long[] PRICES = {-120000, 0, 18, 20000, 40000, 50000, 60000, 64000, 80000, 99000};
    @Autowired
    private OrderMapper orderMapper;

    @Test
    //@Disabled
    void save() {
        ThreadLocalRandom random = ThreadLocalRandom.current();

        Date[] dates = create();
        IntStream.range(0, 20).forEach(i -> {
            Order order = new Order();
            order.setOrderId(System.nanoTime() + i);
            order.setPrice(PRICES[i % PRICES.length]);
            order.setAddressId(i);
            order.setCity(CITIES[i % 2]);
            order.setUserId(Math.abs(random.nextInt()));
            order.setCreator("user.0" + i);
            order.setIntervalTime(dates[i % 5]);
            order.setUpdater(order.getCreator());
            log.info("====>{}", order);
            orderMapper.save(order);
        });
    }

    @Test
   // @Disabled
    void findAll() {
        List<Order> list = orderMapper.findAllAtPrice(60000);
        log.info("===>{}", list);
    }

    private Date[] create() {
        Date[] dates = new Date[6];

        try {
            Date date = DateUtils.parseDate("2023-08-14 00:00:00", Locale.CHINA, "yyyy-MM-dd HH:mm:ss");
            IntStream.range(0, 6).forEach(i -> dates[i] = DateUtils.addDays(date, i));
        } catch (ParseException e) {
            log.error("date parse fail: ", e);
        }
        return dates;
    }
}

運(yùn)行結(jié)果

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

復(fù)合分片(根據(jù)城市和order_id分片)

application.yml配置

rules:
  sharding:
    sharding-algorithms:
      t-order-algorithm:
        type: COMPLEX_INLINE
        props:
          algorithm-expression: t_order_$->{city}_$->{order_id % 2}
          sharding-columns: city,order_id
    tables:
      t_order:
        actual-data-nodes: ds.t_order_$->{['shanghai','beijing']}_$->{0..1}
        table-strategy:
          complex:
            sharding-algorithm-name: t-order-algorithm
            sharding-columns: city,order_id

分片結(jié)果

在這里插入圖片描述

在這里插入圖片描述

到此這篇關(guān)于使用ShardingSphere實(shí)現(xiàn)MySQL分庫分表的文章就介紹到這了,更多相關(guān)ShardingSphere MySQL分庫分表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論