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

使用ShardingJDBC進(jìn)行數(shù)據(jù)分片以及讀寫分離

 更新時(shí)間:2024年01月31日 08:22:44   作者:一只愛(ài)擼貓的程序猿  
ShardingJDBC是一個(gè)輕量級(jí)的Java框架,提供了數(shù)據(jù)分片、讀寫分離、分布式主鍵生成等數(shù)據(jù)訪問(wèn)功能,本文將給大家介紹如何使用ShardingJDBC進(jìn)行數(shù)據(jù)分片以及讀寫分離,需要的朋友可以參考下

簡(jiǎn)述

  • ShardingJDBC: 它是一個(gè)輕量級(jí)的Java框架,提供了數(shù)據(jù)分片、讀寫分離、分布式主鍵生成等數(shù)據(jù)訪問(wèn)功能。ShardingJDBC 直接嵌入在應(yīng)用程序中,不需要通過(guò)中間件代理的方式實(shí)現(xiàn)數(shù)據(jù)庫(kù)訪問(wèn)。
  • 多數(shù)據(jù)源: 在 ShardingJDBC 中,多數(shù)據(jù)源指的是將數(shù)據(jù)儲(chǔ)存到多個(gè)數(shù)據(jù)庫(kù)中。數(shù)據(jù)根據(jù)某種分片策略(如按照ID范圍、哈希值等)分布在不同的數(shù)據(jù)庫(kù)中。
  • 讀寫分離: 讀寫分離是通過(guò)配置主庫(kù)(寫操作)和從庫(kù)(讀操作)來(lái)實(shí)現(xiàn)的。應(yīng)用程序?qū)懭氩僮髦饕槍?duì)主庫(kù),讀取操作可以分散到多個(gè)從庫(kù)中,從而提高數(shù)據(jù)庫(kù)的讀取性能和系統(tǒng)的可擴(kuò)展性。

原理

ShardingJDBC 的核心組件和功能,包括一些相關(guān)代碼片段以更好地理解其工作原理。

1. SQL 解析

SQL 解析是 ShardingJDBC 處理流程的起點(diǎn)。ShardingJDBC 使用 ANTLR(另一個(gè)語(yǔ)言識(shí)別工具)作為 SQL 解析工具。

  • SQL解析類SQLParseEngine 是解析的入口點(diǎn)。它接收原始 SQL 語(yǔ)句并基于數(shù)據(jù)庫(kù)方言(MySQL、PostgreSQL 等)進(jìn)行解析。
  • 解析過(guò)程:解析過(guò)程包括詞法分析和語(yǔ)法分析,用于構(gòu)建抽象語(yǔ)法樹(shù)(AST)。AST 提供了 SQL 結(jié)構(gòu)的詳細(xì)視圖,包括表名、列名、條件等。

SQLParseEngine 源碼分析

public final class SQLParseEngine {
    private final DatabaseType databaseType;
    private final String sql;
    private final LexerEngine lexerEngine;
    private final SQLStatementParser statementParser;

    public SQLParseEngine(DatabaseType databaseType, String sql, Properties properties, List<SQLToken> sqlTokens) {
        this.databaseType = databaseType;
        this.sql = sql;
        Lexer lexer = LexerFactory.newInstance(databaseType, sql);
        this.lexerEngine = new LexerEngine(lexer);
        this.statementParser = SQLStatementParserFactory.newInstance(databaseType, lexerEngine);
    }

    public SQLStatement parse() {
        lexerEngine.nextToken();
        return statementParser.parse();
    }
}

在上面的代碼中,SQLParseEngine 使用了數(shù)據(jù)庫(kù)類型(DatabaseType)和 SQL 語(yǔ)句來(lái)初始化。它首先創(chuàng)建一個(gè) Lexer(詞法解析器),然后使用這個(gè) Lexer 創(chuàng)建一個(gè) LexerEngine,并且基于數(shù)據(jù)庫(kù)類型創(chuàng)建相應(yīng)的 SQL 語(yǔ)句解析器。parse 方法最終返回一個(gè) SQL 語(yǔ)句對(duì)象(SQLStatement),這個(gè)對(duì)象代表了解析后的 SQL 語(yǔ)句。

2. 路由計(jì)算

路由是根據(jù)分片策略和解析出的 SQL 信息,確定 SQL 應(yīng)該執(zhí)行在哪些具體的數(shù)據(jù)庫(kù)和表上。

  • 路由類ShardingRouter 負(fù)責(zé)執(zhí)行路由邏輯。
  • 路由策略:通過(guò)實(shí)現(xiàn) ShardingStrategy 接口的類(如 StandardShardingStrategy、ComplexShardingStrategy),根據(jù)分片鍵和分片算法確定目標(biāo)數(shù)據(jù)源。

ShardingRouter 源碼分析

public final class ShardingRouter {
    private final ShardingRule shardingRule;

    public ShardingRouter(ShardingRule shardingRule) {
        this.shardingRule = shardingRule;
    }

    public RoutingResult route(final SQLStatement sqlStatement) {
        // 省略具體路由邏輯
    }
}

在這里,ShardingRouter 通過(guò) ShardingRule(包含分片策略和規(guī)則)來(lái)進(jìn)行初始化。route 方法接受一個(gè) SQL 語(yǔ)句對(duì)象,并根據(jù)分片規(guī)則返回路由結(jié)果。

3. SQL 改寫

根據(jù)路由結(jié)果,ShardingJDBC 會(huì)改寫原始 SQL,使其適用于目標(biāo)的物理數(shù)據(jù)庫(kù)和表。

  • 改寫類SQLRewriteEngine 負(fù)責(zé) SQL 改寫。
  • 改寫過(guò)程:根據(jù)路由結(jié)果和 AST,SQLRewriteEngine 會(huì)修改表名、增加額外的條件等,生成最終要執(zhí)行的 SQL。

SQLRewriteEngine 源碼分析

public final class SQLRewriteEngine {
    private final SQLStatement sqlStatement;
    private final List<SQLToken> sqlTokens;

    public SQLRewriteEngine(SQLStatement sqlStatement) {
        this.sqlStatement = sqlStatement;
        this.sqlTokens = new LinkedList<>();
    }

    public String rewrite() {
        // 省略具體改寫邏輯
    }
}

這里的 SQLRewriteEngine 接收一個(gè) SQL 語(yǔ)句對(duì)象,并根據(jù)路由結(jié)果和 SQL 語(yǔ)句中的令牌(SQLToken)列表來(lái)改寫 SQL。

4. 執(zhí)行計(jì)劃生成與執(zhí)行

生成 SQL 的執(zhí)行計(jì)劃并在相應(yīng)的數(shù)據(jù)庫(kù)實(shí)例上執(zhí)行。

  • 執(zhí)行類ShardingExecuteEngine 負(fù)責(zé)管理 SQL 的執(zhí)行。
  • 執(zhí)行過(guò)程:它可能涉及到并行查詢、合并結(jié)果集等操作。對(duì)于寫操作,通常直接路由到主庫(kù);對(duì)于讀操作,則可能涉及到多個(gè)從庫(kù)。
public class ShardingExecuteEngine implements AutoCloseable {
    private final ExecutorService executorService;

    public ShardingExecuteEngine(int executorSize) {
        this.executorService = Executors.newFixedThreadPool(executorSize);
    }

    // 省略執(zhí)行方法
}

ShardingExecuteEngine 使用一個(gè)線程池來(lái)執(zhí)行 SQL。這個(gè)類負(fù)責(zé)管理 SQL 的執(zhí)行過(guò)程,包括可能的并行查詢和結(jié)果集合并。

5. 結(jié)果集合并

對(duì)于查詢操作,ShardingJDBC 需要合并來(lái)自不同物理表或數(shù)據(jù)庫(kù)的結(jié)果集。

  • 合并類MergeEngine 負(fù)責(zé)結(jié)果集的合并。
  • 合并過(guò)程:根據(jù)不同的查詢類型(聚合查詢、排序查詢等),MergeEngine 使用不同的合并策略來(lái)確保返回給用戶的是一個(gè)統(tǒng)一的結(jié)果集。
public final class MergeEngine {
    public MergedResult merge(List<QueryResult> queryResults, SQLStatement sqlStatement) {
        // 省略合并邏輯
    }
}

MergeEngine 負(fù)責(zé)將來(lái)自不同物理表或數(shù)據(jù)庫(kù)的查詢結(jié)果合并成一個(gè)統(tǒng)一的結(jié)果集。它根據(jù) SQL 語(yǔ)句的類型(如聚合查詢、排序查詢)來(lái)應(yīng)用不同的合并策略。

6. 分布式事務(wù)處理

處理分布式環(huán)境下的事務(wù)一致性。

  • 事務(wù)管理器ShardingTransactionManager 接口定義了事務(wù)管理的行為。
  • 具體實(shí)現(xiàn):如 XAShardingTransactionManager 用于處理 XA 類型的分布式事務(wù)。

ShardingTransactionManager 接口和 XAShardingTransactionManager 實(shí)現(xiàn)

public interface ShardingTransactionManager {
    void begin();
    void commit();
    void rollback();
    // 省略其他方法
}

public class XAShardingTransactionManager implements ShardingTransactionManager {
    // 實(shí)現(xiàn)分布式事務(wù)管理邏輯
}

ShardingTransactionManager 接口定義了事務(wù)管理的基本行為,如開(kāi)始(begin)、提交(commit)和回滾(rollback)操作。XAShardingTransactionManager 是這個(gè)接口的一個(gè)實(shí)現(xiàn),用于處理 XA 類型的分布式事務(wù)。

我們將假設(shè)有兩個(gè)業(yè)務(wù)表:orderuser,并且這兩個(gè)表需要根據(jù)不同的策略進(jìn)行分片。同時(shí),我們將設(shè)置四個(gè)數(shù)據(jù)源(兩個(gè)主庫(kù)和兩個(gè)從庫(kù))來(lái)實(shí)現(xiàn)讀寫分離。

實(shí)際案例

場(chǎng)景設(shè)定

  • 數(shù)據(jù)源ds0、ds0_slave、ds1、ds1_slave。其中 ds0ds1 是主庫(kù),ds0_slaveds1_slave 是從庫(kù)。
  • 業(yè)務(wù)表orderuser。
  • 分片策略
    • order 表按照訂單ID分片。
    • user 表按照用戶ID分片。
  • 讀寫分離:所有寫操作都發(fā)生在主庫(kù),讀操作可以分配到從庫(kù)。

配置和代碼實(shí)現(xiàn)

添加依賴:

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>YOUR_VERSION</version>
</dependency>

配置文件 application.yml:

spring:
  shardingsphere:
    datasource:
      names: ds0,ds0_slave,ds1,ds1_slave
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: YOUR_DRIVER_CLASS
        jdbc-url: JDBC_URL_FOR_DS0
        username: YOUR_USERNAME
        password: YOUR_PASSWORD
      ds0_slave:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: YOUR_DRIVER_CLASS
        jdbc-url: JDBC_URL_FOR_DS0_SLAVE
        username: YOUR_USERNAME
        password: YOUR_PASSWORD
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: YOUR_DRIVER_CLASS
        jdbc-url: JDBC_URL_FOR_DS1
        username: YOUR_USERNAME
        password: YOUR_PASSWORD
      ds1_slave:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: YOUR_DRIVER_CLASS
        jdbc-url: JDBC_URL_FOR_DS1_SLAVE
        username: YOUR_USERNAME
        password: YOUR_PASSWORD
    sharding:
      tables:
        order:
          actual-data-nodes: ds${0..1}.order_${0..1}
          table-strategy:
            inline:
              sharding-column: id
              algorithm-expression: order_${id % 2}
          database-strategy:
            inline:
              sharding-column: user_id
              algorithm-expression: ds${user_id % 2}
          key-generator:
            type: SNOWFLAKE
            column: id
        user:
          actual-data-nodes: ds${0..1}.user_${0..1}
          table-strategy:
            inline:
              sharding-column: id
              algorithm-expression: user_${id > 5000 ? 1 : 0}
          database-strategy:
            inline:
              sharding-column: id
              algorithm-expression: ds${id % 2}
          key-generator:
            type: SNOWFLAKE
            column: id
      master-slave-rules:
        ds0:
          master-data-source-name: ds0
          slave-data-source-names: ds0_slave
        ds1:
          master-data-source-name: ds1
          slave-data-source-names: ds1_slave

這段配置是用于設(shè)置 Apache ShardingSphere(ShardingJDBC 的一個(gè)部分)的 YAML 格式的配置文件,專門用于 Spring Boot 項(xiàng)目。它定義了數(shù)據(jù)源(包括主從數(shù)據(jù)源),表的分片策略,以及主從復(fù)制規(guī)則。讓我們逐個(gè)部分進(jìn)行詳細(xì)解釋:

數(shù)據(jù)源配置

datasource:
  names: ds0,ds0_slave,ds1,ds1_slave
  ds0:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: YOUR_DRIVER_CLASS
    jdbc-url: JDBC_URL_FOR_DS0
    username: YOUR_USERNAME
    password: YOUR_PASSWORD
  ...
  • names: 定義了所有數(shù)據(jù)源的名稱,這里有四個(gè)數(shù)據(jù)源:ds0, ds0_slave, ds1, ds1_slave。
  • ds0, ds0_slave, ds1, ds1_slave: 分別定義了四個(gè)數(shù)據(jù)源的詳細(xì)配置。
  • type: 數(shù)據(jù)源類型,這里使用的是 HikariCP 連接池。
  • driver-class-name: 數(shù)據(jù)庫(kù)驅(qū)動(dòng)類。
  • jdbc-url: 數(shù)據(jù)庫(kù)的 JDBC URL。
  • usernamepassword: 數(shù)據(jù)庫(kù)的登錄用戶名和密碼。

分片配置

sharding:
  tables:
    order:
      actual-data-nodes: ds${0..1}.order_${0..1}
      table-strategy:
        inline:
          sharding-column: id
          algorithm-expression: order_${id % 2}
      database-strategy:
        inline:
          sharding-column: user_id
          algorithm-expression: ds${user_id % 2}
      key-generator:
        type: SNOWFLAKE
        column: id
    user:
      ...
  • sharding: 定義了分片的總體配置。
  • tables: 在這里定義具體的表和它們的分片策略。
  • order: 這是一個(gè)表的名稱。
  • actual-data-nodes: 定義實(shí)際的數(shù)據(jù)節(jié)點(diǎn),ds${0..1}.order_${0..1} 表示 order 表在 ds0ds1 數(shù)據(jù)源上都有兩個(gè)分片,即 order_0order_1。
  • table-strategy: 定義表的分片策略。
    • sharding-column: 分片鍵,這里使用 id。
    • algorithm-expression: 分片算法表達(dá)式,這里是簡(jiǎn)單的模 2 運(yùn)算。
  • database-strategy: 定義數(shù)據(jù)庫(kù)的分片策略,類似于表的分片策略。
  • key-generator: 定義主鍵生成策略,這里使用的是雪花算法(SNOWFLAKE)。

主從配置

master-slave-rules:
  ds0:
    master-data-source-name: ds0
    slave-data-source-names: ds0_slave
  ds1:
    master-data-source-name: ds1
    slave-data-source-names: ds1_slave

實(shí)體類和數(shù)據(jù)訪問(wèn)層:

定義 Order 和 User 實(shí)體類,以及對(duì)應(yīng)的 JPA 倉(cāng)庫(kù)或 MyBatis 映射。

Order 實(shí)體類

@Entity
@Table(name = "order")
public class Order {
    @Id
    private Long id;

    @Column(name = "user_id")
 private Long userId;

    @Column(name = "order_amount")
    private BigDecimal orderAmount;

 // 標(biāo)準(zhǔn)的構(gòu)造函數(shù)、getter 和 setter
    public Order() {
    }

    // ... 省略其他構(gòu)造函數(shù)、getter 和 setter 方法

    // ... 可以添加業(yè)務(wù)邏輯方法
}

User 實(shí)體類

@Entity
@Table(name = "user")
public class User {
    @Id
    private Long id;

    @Column(name = "username")
    private String username;

    @Column(name = "email")
    private String email;

    // 標(biāo)準(zhǔn)的構(gòu)造函數(shù)、getter 和 setter
    public User() {
    }

    // ... 省略其他構(gòu)造函數(shù)、getter 和 setter 方法

    // ... 可以添加業(yè)務(wù)邏輯方法
}

OrderRepository 接口

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByUserId(Long userId);

    // ... 可以根據(jù)需要添加其他查詢方法
}

UserRepository 接口

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);

    // ... 可以根據(jù)需要添加其他查詢方法
}

補(bǔ)充一個(gè)mybatis的寫法:

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User findById(Long id);

    @Insert("INSERT INTO user (username, email) VALUES (#{username}, #{email})")
    void insert(User user);

    // 更多的 MyBatis SQL 映射可以根據(jù)需要添加
}

總結(jié)

ShardingJDBC 的源碼實(shí)現(xiàn)體現(xiàn)了其作為一個(gè)數(shù)據(jù)庫(kù)中間件框架的復(fù)雜性和靈活性。它將 SQL 解析、路由、改寫、執(zhí)行和結(jié)果集合并等多個(gè)步驟封裝成一系列高度解耦的組件和接口。這種設(shè)計(jì)使得 ShardingJDBC 能夠靈活地適應(yīng)各種數(shù)據(jù)庫(kù)和 SQL 方言,同時(shí)提供豐富的分片策略和讀寫分離功能。

以上就是使用ShardingJDBC進(jìn)行數(shù)據(jù)分片以及讀寫分離的詳細(xì)內(nèi)容,更多關(guān)于ShardingJDBC數(shù)據(jù)分片的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • startActivityForResult和setResult案例詳解

    startActivityForResult和setResult案例詳解

    這篇文章主要介紹了startActivityForResult和setResult案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java連接數(shù)據(jù)庫(kù)步驟解析(Oracle、MySQL)

    Java連接數(shù)據(jù)庫(kù)步驟解析(Oracle、MySQL)

    本文主要介紹了Java連接Oracle數(shù)據(jù)庫(kù)和MySQL數(shù)據(jù)庫(kù)的步驟解析。具有很好的參考價(jià)值,需要的朋友一起來(lái)看下吧
    2016-12-12
  • JAVA中阻止類的繼承(官方和非官方)

    JAVA中阻止類的繼承(官方和非官方)

    在面向?qū)ο蟮睦碚撝? 有一些方案要求你用一個(gè)辦法來(lái)聲明一個(gè)不可繼承的類。一般而言,如果類提供的功能不應(yīng)該被改變,或者更恰當(dāng)?shù)恼f(shuō),是被覆蓋(override)的時(shí)候才會(huì)出現(xiàn)這種情況。在這篇文章里,我討論在JAVA語(yǔ)言中的實(shí)現(xiàn)辦法--官方和非官方的辦法
    2014-01-01
  • Java中@Accessors注解的具體使用

    Java中@Accessors注解的具體使用

    @Accessors是Lombok提供的注解之一,用于自動(dòng)生成getter和setter方法,本文主要介紹了@Accessors注解的常用屬性,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • SpringBoot深入探究@Conditional條件裝配的使用

    SpringBoot深入探究@Conditional條件裝配的使用

    這篇文章主要為大家介紹了SpringBoot底層注解@Conditional的使用分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Kotlin中使用Java數(shù)據(jù)類時(shí)引發(fā)的Bug解決方式

    Kotlin中使用Java數(shù)據(jù)類時(shí)引發(fā)的Bug解決方式

    這篇文章主要介紹了Kotlin中使用Java數(shù)據(jù)類時(shí)引發(fā)的一個(gè)Bug,本文給大家分享問(wèn)題解決方式,感興趣的朋友跟隨小編一起看看吧
    2023-09-09
  • 一篇文章了解Jackson注解@JsonFormat及失效解決辦法

    一篇文章了解Jackson注解@JsonFormat及失效解決辦法

    這篇文章主要給大家介紹了關(guān)于如何通過(guò)一篇文章了解Jackson注解@JsonFormat及失效解決辦法的相關(guān)資料,@JsonFormat注解是一個(gè)時(shí)間格式化注解,用于格式化時(shí)間,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • Java實(shí)現(xiàn)WebSocket客戶端詳細(xì)步驟

    Java實(shí)現(xiàn)WebSocket客戶端詳細(xì)步驟

    這篇文章主要介紹了如何使用Java實(shí)現(xiàn)一個(gè)功能全面的WebSocket客戶端,包括引入依賴、創(chuàng)建客戶端類、實(shí)現(xiàn)連接、發(fā)送和接收消息、處理復(fù)雜消息、實(shí)現(xiàn)心跳機(jī)制、重連策略、異常處理、線程安全的隊(duì)列以及測(cè)試和調(diào)試,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • springboot之Validation參數(shù)校驗(yàn)詳細(xì)解讀

    springboot之Validation參數(shù)校驗(yàn)詳細(xì)解讀

    這篇文章主要介紹了springboot之Validation參數(shù)校驗(yàn)詳細(xì)解讀,本篇是關(guān)于springboot的參數(shù)校驗(yàn)知識(shí),當(dāng)然也適用其它java應(yīng)用,讀完本篇將學(xué)會(huì)基本的參數(shù)校驗(yàn),自定義參數(shù)校驗(yàn)和分組參數(shù)校驗(yàn),需要的朋友可以參考下
    2023-10-10
  • JavaWeb實(shí)體類轉(zhuǎn)為json對(duì)象的實(shí)現(xiàn)方法

    JavaWeb實(shí)體類轉(zhuǎn)為json對(duì)象的實(shí)現(xiàn)方法

    這篇文章主要介紹了JavaWeb實(shí)體類轉(zhuǎn)為json對(duì)象的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評(píng)論