Linux

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > Linux > Apache ShardingSphere使用

Apache ShardingSphere简介及使用详解

作者:茫茫人海一粒沙

Apache ShardingSphere 是一款开源的分布式数据库生态系统,主要用于实现数据库的分片、读写分离和全链路压测等功能,下面给大家介绍Apache ShardingSphere 初识使用,感兴趣的朋友跟随小编一起看看吧

一 什么是 ShardingSphere?

1.1 背景:为什么需要分库分表?

随着系统数据量和用户量不断增长,传统单体数据库容易遇到瓶颈:

为了解决这些问题,开发者往往采用 分库分表 技术,将一张大表分成多个小表,分布在不同数据库中,实现水平扩展和负载均衡。

1.2 什么是 Apache ShardingSphere?

Apache ShardingSphere 是一款开源的 分布式数据库中间件框架,可以帮助开发者轻松实现:

ShardingSphere 核心组件包括:

组件说明
ShardingSphere-JDBCJDBC 封装层,嵌入应用中,适用于微服务架构
ShardingSphere-Proxy独立部署的数据库代理,支持多语言访问
ShardingSphere-Sidecar(规划中)面向云原生场景,Service Mesh 结构

1.3 ShardingSphere-JDBC 的核心功能

功能简要说明
分库分表按字段配置路由策略,自动将 SQL 分发到对应的数据库/表
读写分离自动区分读写请求,路由到主/从数据库
灵活分片策略支持取模、范围、Hint、自定义算法等多种策略
事务支持支持本地事务和分布式事务(Seata/XA)
透明化使用对开发者来说使用方式与普通 JDBC 几乎一致,只需配置逻辑表名

二、实践部分:Java + H2 实现分库分表

示例:使用 Java 原生程序 + ShardingSphere-JDBC + H2 内存数据库,模拟一个电商订单系统按 user_id 分库,order_id 分表。

2.1 项目结构

2.2 Maven 依赖配置

<dependencies>
    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>shardingsphere-jdbc-core</artifactId>
        <version>5.4.1</version>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>2.2.220</version>
    </dependency>
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
        <version>5.0.1</version>
    </dependency>
</dependencies>

2.3 核心代码结构

1. 创建真实表(物理分表)

public static void createTables() throws SQLException {
    for (int i = 0; i < 2; i++) {
        String db = "ds" + i;
        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:" + db + ";DB_CLOSE_DELAY=-1;MODE=MySQL", "sa", "")) {
            Statement stmt = conn.createStatement();
            for (int j = 0; j < 2; j++) {
                stmt.execute(String.format("""
                    CREATE TABLE IF NOT EXISTS t_order_%d (
                        order_id BIGINT PRIMARY KEY,
                        user_id INT,
                        status VARCHAR(50)
                    )
                """, j));
            }
        }
    }
}

2. 配置分库分表数据源

public static DataSource createDataSource() throws SQLException {
    Map<String, DataSource> dataSourceMap = new HashMap<>();
    for (int i = 0; i < 2; i++) {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:h2:mem:ds" + i + ";DB_CLOSE_DELAY=-1;MODE=MySQL");
        ds.setUsername("sa");
        ds.setPassword("");
        dataSourceMap.put("ds" + i, ds);
    }
    ShardingTableRuleConfiguration orderTableRule = new ShardingTableRuleConfiguration(
        "t_order", "ds${0..1}.t_order_${0..1}");
    orderTableRule.setDatabaseShardingStrategy(
        new StandardShardingStrategyConfiguration("user_id", "dbSharding"));
    orderTableRule.setTableShardingStrategy(
        new StandardShardingStrategyConfiguration("order_id", "tableSharding"));
    ShardingRuleConfiguration config = new ShardingRuleConfiguration();
    config.getTables().add(orderTableRule);
    config.getShardingAlgorithms().put("dbSharding",
        new AlgorithmConfiguration("INLINE", props("algorithm-expression", "ds${user_id % 2}")));
    config.getShardingAlgorithms().put("tableSharding",
        new AlgorithmConfiguration("INLINE", props("algorithm-expression", "t_order_${order_id % 2}")));
    return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, List.of(config), new Properties());
}

3. 插入与查询数据

public static void insertOrder(DataSource ds, long orderId, int userId, String status) throws SQLException {
    try (Connection conn = ds.getConnection()) {
        PreparedStatement ps = conn.prepareStatement("INSERT INTO t_order (order_id, user_id, status) VALUES (?, ?, ?)");
        ps.setLong(1, orderId);
        ps.setInt(2, userId);
        ps.setString(3, status);
        ps.executeUpdate();
    }
}
public static void queryOrders(DataSource ds) throws SQLException {
    try (Connection conn = ds.getConnection()) {
        ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM t_order");
        while (rs.next()) {
            System.out.printf("order_id=%d, user_id=%d, status=%s%n",
                    rs.getLong("order_id"),
                    rs.getInt("user_id"),
                    rs.getString("status"));
        }
    }
}

2.4 程序入口

public static void main(String[] args) throws Exception {
    createTables();  // 创建实际分表
    DataSource shardingDataSource = createDataSource();
    insertOrder(shardingDataSource, 1001, 1, "INIT");
    insertOrder(shardingDataSource, 1002, 2, "PAID");
    insertOrder(shardingDataSource, 1003, 3, "SHIPPED");
    queryOrders(shardingDataSource);
}

输出示例

order_id=1001, user_id=1, status=INIT
order_id=1002, user_id=2, status=PAID
order_id=1003, user_id=3, status=SHIPPED

ShardingSphere 已自动根据你配置的策略将数据路由到对应的库和表!

总结

Apache ShardingSphere 提供了强大、灵活的分库分表能力,通过合理配置可以极大提升系统的性能与扩展性:

无论你是中小项目的快速原型,还是大规模高并发系统,ShardingSphere 都是一个值得一试的解决方案。

完整代码

package org.example;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
import javax.sql.DataSource;
import java.sql.*;
import java.util.*;
public class ShardingH2Example {
    public static void main(String[] args) throws Exception {
        createTables(); //  注意:用 DriverManager 直连底层 db 建表
        DataSource shardingDataSource = createDataSource();
        // 插入测试数据
        insertOrder(shardingDataSource, 1001, 1, "INIT");
        insertOrder(shardingDataSource, 1002, 2, "PAID");
        insertOrder(shardingDataSource, 1003, 3, "SHIPPED");
        // 查询测试数据
        queryOrders(shardingDataSource);
    }
    public static DataSource createDataSource() throws Exception {
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        // 模拟两个库:ds0 和 ds1(分别用两个内存 H2 实例模拟)
        for (int i = 0; i < 2; i++) {
            HikariDataSource ds = new HikariDataSource();
            ds.setJdbcUrl("jdbc:h2:mem:ds" + i + ";DB_CLOSE_DELAY=-1;MODE=MySQL");
            ds.setUsername("sa");
            ds.setPassword("");
            dataSourceMap.put("ds" + i, ds);
        }
        // 分表规则配置
        ShardingTableRuleConfiguration orderTableRule = new ShardingTableRuleConfiguration(
                "t_order", "ds${0..1}.t_order_${0..1}");
        // 分库策略(user_id)
        orderTableRule.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration(
                "user_id", "dbSharding"));
        // 分表策略(order_id)
        orderTableRule.setTableShardingStrategy(new StandardShardingStrategyConfiguration(
                "order_id", "tableSharding"));
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTables().add(orderTableRule);
        Properties dbProps = new Properties();
        dbProps.setProperty("algorithm-expression", "ds${user_id % 2}");
        shardingRuleConfig.getShardingAlgorithms().put("dbSharding",
                new AlgorithmConfiguration("INLINE", dbProps));
        Properties tableProps = new Properties();
        tableProps.setProperty("algorithm-expression", "t_order_${order_id % 2}");
        shardingRuleConfig.getShardingAlgorithms().put("tableSharding",
                new AlgorithmConfiguration("INLINE", tableProps));
        return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, List.of(shardingRuleConfig), new Properties());
    }
    public static void createTables() throws SQLException {
        for (int i = 0; i < 2; i++) {
            String dbName = "ds" + i;
            try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:" + dbName + ";DB_CLOSE_DELAY=-1;MODE=MySQL", "sa", "")) {
                Statement stmt = conn.createStatement();
                for (int j = 0; j < 2; j++) {
                    String sql = String.format("""
                        CREATE TABLE IF NOT EXISTS t_order_%d (
                            order_id BIGINT PRIMARY KEY,
                            user_id INT,
                            status VARCHAR(50)
                        )
                """, j);
                    stmt.execute(sql);
                }
            }
        }
    }
    // 辅助方法用于手动连接底层 H2 数据源
    private static HikariDataSource getH2DataSource(String name) {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:h2:mem:" + name + ";DB_CLOSE_DELAY=-1;MODE=MySQL");
        ds.setUsername("sa");
        ds.setPassword("");
        return ds;
    }
    public static void insertOrder(DataSource ds, long orderId, int userId, String status) throws SQLException {
        try (Connection conn = ds.getConnection()) {
            PreparedStatement ps = conn.prepareStatement("INSERT INTO t_order (order_id, user_id, status) VALUES (?, ?, ?)");
            ps.setLong(1, orderId);
            ps.setInt(2, userId);
            ps.setString(3, status);
            ps.executeUpdate();
        }
    }
    public static void queryOrders(DataSource ds) throws SQLException {
        try (Connection conn = ds.getConnection()) {
            ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM t_order");
            System.out.println("Query Results:");
            while (rs.next()) {
                System.out.printf("order_id: %d, user_id: %d, status: %s%n",
                        rs.getLong("order_id"),
                        rs.getInt("user_id"),
                        rs.getString("status"));
            }
        }
    }
}

到此这篇关于Apache ShardingSphere 初识使用的文章就介绍到这了,更多相关Apache ShardingSphere使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文