当前位置: 首页 > news >正文

ShardingSphere 分库分表技术实现与实战案例

ShardingSphere 分库分表技术实现与实战案例

1. 引言

1.1 背景与问题

随着业务的快速发展,数据库中的数据量急剧增长,单表数据量可能达到数千万甚至数亿条。此时,传统的单库单表架构会面临以下挑战:

  • 查询性能显著下降,SQL执行耗时增加
  • 索引膨胀,维护成本增高
  • 数据库备份和恢复耗时过长
  • 单点故障风险高,可用性难以保障

分库分表技术通过将数据分散存储到多个数据库和表中,解决了单库单表的性能瓶颈,是大型系统数据库架构演进的必经之路。

1.2 分库分表概念

  • 分库:将单一数据库按照某种规则拆分到多个数据库实例上,降低单库压力
  • 分表:将单一表按照某种规则拆分到多个表中,解决单表数据量大的问题
  • 水平拆分:按行拆分数据,同一表的不同行分布到不同库表中
  • 垂直拆分:按列拆分数据,将表中不同列拆分到不同表中

1.3 选型介绍

本文档采用 Apache ShardingSphere 作为分库分表解决方案,它是一套开源的分布式数据库中间件解决方案,包含:

  • Sharding-JDBC:基于JDBC的客户端分库分表组件
  • Sharding-Proxy:基于数据库代理的分库分表组件
  • Sharding-Sidecar:基于Service Mesh的分库分表组件

本文重点介绍 Sharding-JDBC 的实现方式,它具有性能好、对应用侵入性小等特点。

2. ShardingSphere 核心原理

2.1 数据分片核心概念

  • 逻辑表:用户SQL中操作的表名,如t_order
  • 实际表:物理存在的表,如t_order_0t_order_1
  • 数据节点:由数据源和数据表组成的单元,如db0.t_order_0
  • 分片键:用于分片的字段,如user_idorder_id
  • 分片算法:根据分片键计算数据应路由到哪个节点的算法

2.2 分片策略

ShardingSphere支持多种分片策略:

  • 精确分片策略:根据分片键精确值路由
  • 范围分片策略:根据分片键的范围路由
  • 复合分片策略:根据多个分片键组合路由
  • Hint分片策略:通过Hint指定分片路由

2.3 执行流程

  1. SQL解析:解析SQL,提取表名、字段、条件等信息
  2. 分片路由:根据分片规则计算数据应路由到的节点
  3. SQL改写:将逻辑表名改写为实际表名
  4. SQL执行:在所有目标节点执行改写后的SQL
  5. 结果合并:将多个节点的执行结果合并返回

3. 环境准备

3.1 软件版本

  • JDK:1.8+
  • Spring Boot:2.7.x
  • ShardingSphere:5.3.2
  • MySQL:8.0.x
  • MyBatis:3.5.x

3.2 数据库环境

准备2个数据库实例(db0和db1),后续将在这两个库中创建分表:

-- 创建数据库
CREATE DATABASE IF NOT EXISTS db0 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS db1 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

4. 完整实战案例

4.1 案例背景

某电商平台需要对以下核心表进行分库分表:

  • 订单表(t_order)
  • 订单项表(t_order_item)
  • 用户表(t_user)

预计订单表年增长1亿条,用户表总数据量5000万。

4.2 分片策略设计

表名分库策略分表策略分片键
t_order按user_id哈希取模(2个库)按create_time年月分表user_id, create_time
t_order_item与订单表同库(按order_id哈希)与订单表同表(按时间)order_id, create_time
t_user按user_id哈希取模(2个库)按user_id范围分表(每个库2张表)user_id

设计原则

  • 关联表使用相同分片策略,确保关联数据在同一库,避免跨库join
  • 订单表按用户+时间分片,便于查询用户历史订单
  • 用户表按ID范围分片,便于扩容

4.3 项目实现

4.3.1 引入依赖
<dependencies><!-- Spring Boot 核心 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Sharding-JDBC --><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.3.2</version></dependency><!-- MySQL 驱动 --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version></dependency><!-- MyBatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><!-- 数据库连接池 --><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>
4.3.2 分库分表配置
spring:shardingsphere:datasource:names: db0,db1db0:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db0?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: rootpassword: roothikari:maximum-pool-size: 10minimum-idle: 5db1:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: rootpassword: roothikari:maximum-pool-size: 10minimum-idle: 5rules:sharding:tables:# 订单表配置t_order:actual-data-nodes: db${0..1}.t_order_${202401..202412}database-strategy:standard:sharding-column: user_idsharding-algorithm-name: order_db_inlinetable-strategy:standard:sharding-column: create_timesharding-algorithm-name: order_table_inlinekey-generator:column: order_idtype: SNOWFLAKEprops:worker-id: 1# 订单项表配置t_order_item:actual-data-nodes: db${0..1}.t_order_item_${202401..202412}database-strategy:standard:sharding-column: order_idsharding-algorithm-name: order_item_db_inlinetable-strategy:standard:sharding-column: create_timesharding-algorithm-name: order_table_inlinekey-generator:column: item_idtype: SNOWFLAKEprops:worker-id: 1# 用户表配置t_user:actual-data-nodes: db${0..1}.t_user_${0..1}database-strategy:standard:sharding-column: user_idsharding-algorithm-name: user_db_inlinetable-strategy:standard:sharding-column: user_idsharding-algorithm-name: user_table_rangekey-generator:column: user_idtype: SNOWFLAKEprops:worker-id: 1# 分片算法配置sharding-algorithms:# 订单表分库算法order_db_inline:type: INLINEprops:algorithm-expression: db${user_id % 2}# 订单项表分库算法order_item_db_inline:type: INLINEprops:algorithm-expression: db${order_id % 2}# 订单表和订单项表共用的分表算法order_table_inline:type: INLINEprops:algorithm-expression: t_order_${date_format(create_time, '%Y%m')}# 用户表分库算法user_db_inline:type: INLINEprops:algorithm-expression: db${user_id % 2}# 用户表分表算法user_table_range:type: RANGEprops:sharding-rules: 0-5000000=t_user_0,5000001-10000000=t_user_1# 绑定表配置,避免跨库关联binding-tables:- t_order,t_order_item# 广播表配置,所有库都有该表且数据一致broadcast-tables:- t_dictprops:sql-show: true  # 显示SQL,调试用check-table-metadata-enabled: false  # 关闭表元数据检查query-with-cipher-column: false
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.example.sharding.entityconfiguration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpl
4.3.3 数据库表结构

在db0和db1中分别创建以下表结构:

-- 订单表(每月一张)
CREATE TABLE `t_order_202401` (`order_id` bigint NOT NULL,`user_id` bigint NOT NULL,`amount` decimal(10,2) NOT NULL,`status` tinyint NOT NULL COMMENT '订单状态',`create_time` datetime NOT NULL,`update_time` datetime NOT NULL,PRIMARY KEY (`order_id`),KEY `idx_user_id` (`user_id`),KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 订单项表(每月一张)
CREATE TABLE `t_order_item_202401` (`item_id` bigint NOT NULL,`order_id` bigint NOT NULL,`product_id` bigint NOT NULL,`quantity` int NOT NULL,`price` decimal(10,2) NOT NULL,`create_time` datetime NOT NULL,PRIMARY KEY (`item_id`),KEY `idx_order_id` (`order_id`),KEY `idx_product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 用户表(分2张表)
CREATE TABLE `t_user_0` (`user_id` bigint NOT NULL,`username` varchar(50) NOT NULL,`phone` varchar(20) DEFAULT NULL,`register_time` datetime NOT NULL,`status` tinyint NOT NULL DEFAULT '1',PRIMARY KEY (`user_id`),UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE `t_user_1` (`user_id` bigint NOT NULL,`username` varchar(50) NOT NULL,`phone` varchar(20) DEFAULT NULL,`register_time` datetime NOT NULL,`status` tinyint NOT NULL DEFAULT '1',PRIMARY KEY (`user_id`),UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 字典表(广播表)
CREATE TABLE `t_dict` (`id` bigint NOT NULL AUTO_INCREMENT,`type` varchar(50) NOT NULL,`code` varchar(50) NOT NULL,`name` varchar(100) NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `uk_type_code` (`type`,`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

注意:需要为每个月创建对应的订单表和订单项表,如t_order_202402、t_order_item_202402等

4.3.4 实体类定义

Order.java

package com.example.sharding.entity;import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;@Data
public class Order {private Long orderId;private Long userId;private BigDecimal amount;private Integer status;private LocalDateTime createTime;private LocalDateTime updateTime;
}

OrderItem.java

package com.example.sharding.entity;import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;@Data
public class OrderItem {private Long itemId;private Long orderId;private Long productId;private Integer quantity;private BigDecimal price;private LocalDateTime createTime;
}

User.java

package com.example.sharding.entity;import lombok.Data;
import java.time.LocalDateTime;@Data
public class User {private Long userId;private String username;private String phone;private LocalDateTime registerTime;private Integer status;
}
4.3.5 Mapper接口与XML

OrderMapper.java

package com.example.sharding.mapper;import com.example.sharding.entity.Order;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;@Mapper
public interface OrderMapper {@Insert("INSERT INTO t_order (user_id, amount, status, create_time, update_time) " +"VALUES (#{userId}, #{amount}, #{status}, #{createTime}, #{updateTime})")void insert(Order order);List<Order> selectByUserIdAndTimeRange(@Param("userId") Long userId,@Param("startTime") String startTime,@Param("endTime") String endTime);Order selectById(@Param("orderId") Long orderId);
}

OrderMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.sharding.mapper.OrderMapper"><select id="selectByUserIdAndTimeRange" resultType="com.example.sharding.entity.Order">SELECT * FROM t_order WHERE user_id = #{userId}AND create_time BETWEEN #{startTime} AND #{endTime}ORDER BY create_time DESC</select><select id="selectById" resultType="com.example.sharding.entity.Order">SELECT * FROM t_order WHERE order_id = #{orderId}</select>
</mapper>

UserMapper.java

package com.example.sharding.mapper;import com.example.sharding.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;@Mapper
public interface UserMapper {@Insert("INSERT INTO t_user (username, phone, register_time, status) " +"VALUES (#{username}, #{phone}, #{registerTime}, #{status})")void insert(User user);User selectById(@Param("userId") Long userId);User selectByUsername(@Param("username") String username);
}
4.3.6 服务层实现

OrderService.java

package com.example.sharding.service;import com.example.sharding.entity.Order;
import com.example.sharding.entity.OrderItem;
import com.example.sharding.mapper.OrderItemMapper;
import com.example.sharding.mapper.OrderMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;@Service
public class OrderService {@Resourceprivate OrderMapper orderMapper;@Resourceprivate OrderItemMapper orderItemMapper;/*** 创建订单及订单项*/@Transactional(rollbackFor = Exception.class)public void createOrder(Order order, List<OrderItem> items) {// 设置订单时间LocalDateTime now = LocalDateTime.now();order.setCreateTime(now);order.setUpdateTime(now);// 插入订单orderMapper.insert(order);// 插入订单项for (OrderItem item : items) {item.setOrderId(order.getOrderId());item.setCreateTime(now);orderItemMapper.insert(item);}}/*** 查询用户在指定时间范围内的订单*/public List<Order> getUserOrders(Long userId, String startTime, String endTime) {return orderMapper.selectByUserIdAndTimeRange(userId, startTime, endTime);}/*** 根据订单ID查询订单*/public Order getOrderById(Long orderId) {return orderMapper.selectById(orderId);}
}

UserService.java

package com.example.sharding.service;import com.example.sharding.entity.User;
import com.example.sharding.mapper.UserMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;@Service
public class UserService {@Resourceprivate UserMapper userMapper;/*** 创建用户*/@Transactional(rollbackFor = Exception.class)public void createUser(User user) {user.setRegisterTime(LocalDateTime.now());user.setStatus(1); // 默认为正常状态userMapper.insert(user);}/*** 根据用户ID查询用户*/public User getUserById(Long userId) {return userMapper.selectById(userId);}/*** 根据用户名查询用户*/public User getUserByUsername(String username) {return userMapper.selectByUsername(username);}
}
4.3.7 控制器实现
package com.example.sharding.controller;import com.example.sharding.entity.Order;
import com.example.sharding.entity.OrderItem;
import com.example.sharding.service.OrderService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;@RestController
@RequestMapping("/orders")
public class OrderController {@Resourceprivate OrderService orderService;@PostMappingpublic String createOrder(@RequestBody OrderCreateRequest request) {orderService.createOrder(request.getOrder(), request.getItems());return "订单创建成功,订单ID:" + request.getOrder().getOrderId();}@GetMapping("/user/{userId}")public List<Order> getUserOrders(@PathVariable Long userId,@RequestParam String startTime,@RequestParam String endTime) {return orderService.getUserOrders(userId, startTime, endTime);}@GetMapping("/{orderId}")public Order getOrderById(@PathVariable Long orderId) {return orderService.getOrderById(orderId);}// 请求参数封装类public static class OrderCreateRequest {private Order order;private List<OrderItem> items;// getter和setter省略public Order getOrder() { return order; }public void setOrder(Order order) { this.order = order; }public List<OrderItem> getItems() { return items; }public void setItems(List<OrderItem> items) { this.items = items; }}
}

4.4 分表自动创建工具

为了避免手动创建每月的分表,我们可以实现一个定时任务自动创建分表:

package com.example.sharding.task;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;@Slf4j
@Component
public class TableAutoCreator {@Resourceprivate DataSource dataSource;// 需要自动创建分表的逻辑表private static final List<String> TABLES_TO_CREATE = Arrays.asList("t_order", "t_order_item");// 数据库列表@Value("${spring.shardingsphere.datasource.names}")private String dataSourceNames;// 每月28号凌晨2点执行,创建下月的分表@Scheduled(cron = "0 0 2 28 * ?")public void createNextMonthTables() {LocalDate nextMonth = LocalDate.now().plusMonths(1);String suffix = nextMonth.format(DateTimeFormatter.ofPattern("yyyyMM"));// 获取所有数据库String[] databases = dataSourceNames.split(",");for (String table : TABLES_TO_CREATE) {for (String db : databases) {String actualTableName = table + "_" + suffix;createTable(db, actualTableName, table);}}}private void createTable(String dbName, String actualTableName, String logicTable) {Connection conn = null;Statement stmt = null;try {// 获取数据库连接conn = dataSource.getConnection();stmt = conn.createStatement();// 切换到目标数据库stmt.execute("USE " + dbName);// 判断表是否已存在boolean tableExists = checkTableExists(conn, actualTableName);if (tableExists) {log.info("表 {} 已存在,无需创建", actualTableName);return;}// 根据逻辑表创建对应的分表String createSql = generateCreateTableSql(actualTableName, logicTable);stmt.execute(createSql);log.info("成功创建表:{}", actualTableName);} catch (Exception e) {log.error("创建表 {} 失败", actualTableName, e);} finally {// 关闭资源try {if (stmt != null) stmt.close();if (conn != null) conn.close();} catch (Exception e) {log.error("关闭数据库连接失败", e);}}}private boolean checkTableExists(Connection conn, String tableName) throws Exception {// 检查表格是否存在的逻辑try (Statement stmt = conn.createStatement()) {stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);return true;} catch (Exception e) {return false;}}private String generateCreateTableSql(String actualTableName, String logicTable) {// 根据不同的逻辑表生成对应的创建表SQLswitch (logicTable) {case "t_order":return "CREATE TABLE `" + actualTableName + "` (" +"  `order_id` bigint NOT NULL," +"  `user_id` bigint NOT NULL," +"  `amount` decimal(10,2) NOT NULL," +"  `status` tinyint NOT NULL COMMENT '订单状态'," +"  `create_time` datetime NOT NULL," +"  `update_time` datetime NOT NULL," +"  PRIMARY KEY (`order_id`)," +"  KEY `idx_user_id` (`user_id`)," +"  KEY `idx_create_time` (`create_time`)" +") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";case "t_order_item":return "CREATE TABLE `" + actualTableName + "` (" +"  `item_id` bigint NOT NULL," +"  `order_id` bigint NOT NULL," +"  `product_id` bigint NOT NULL," +"  `quantity` int NOT NULL," +"  `price` decimal(10,2) NOT NULL," +"  `create_time` datetime NOT NULL," +"  PRIMARY KEY (`item_id`)," +"  KEY `idx_order_id` (`order_id`)," +"  KEY `idx_product_id` (`product_id`)" +") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";default:throw new IllegalArgumentException("不支持的逻辑表:" + logicTable);}}
}

5. 功能测试与验证

5.1 测试场景设计

  1. 创建用户测试
  2. 创建订单及订单项测试
  3. 查询用户订单测试
  4. 分库分表路由正确性验证

5.2 测试代码示例

package com.example.sharding.service;import com.example.sharding.entity.Order;
import com.example.sharding.entity.OrderItem;
import com.example.sharding.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;@SpringBootTest
public class OrderServiceTest {@Resourceprivate UserService userService;@Resourceprivate OrderService orderService;@Testpublic void testCreateAndQueryOrder() {// 1. 创建测试用户User user = new User();user.setUsername("test_user_" + System.currentTimeMillis());user.setPhone("13800138000");userService.createUser(user);System.out.println("创建用户成功,用户ID:" + user.getUserId());// 2. 创建订单Order order = new Order();order.setUserId(user.getUserId());order.setAmount(new BigDecimal("999.00"));order.setStatus(1); // 待支付// 创建订单项List<OrderItem> items = new ArrayList<>();OrderItem item1 = new OrderItem();item1.setProductId(1001L);item1.setQuantity(2);item1.setPrice(new BigDecimal("199.00"));items.add(item1);OrderItem item2 = new OrderItem();item2.setProductId(2002L);item2.setQuantity(1);item2.setPrice(new BigDecimal("599.00"));items.add(item2);// 创建订单orderService.createOrder(order, items);System.out.println("创建订单成功,订单ID:" + order.getOrderId());// 3. 查询订单Order queriedOrder = orderService.getOrderById(order.getOrderId());System.out.println("查询到的订单:" + queriedOrder);// 4. 查询用户订单List<Order> userOrders = orderService.getUserOrders(user.getUserId(), "2024-01-01 00:00:00", "2024-12-31 23:59:59");System.out.println("用户订单数量:" + userOrders.size());}
}

5.3 验证方法

  1. 查看日志:ShardingSphere会输出SQL日志,包含路由信息

    Logic SQL: INSERT INTO t_order (user_id, amount, status, create_time, update_time) VALUES (?, ?, ?, ?, ?)
    SQLStatement: InsertStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.InsertStatement@5f9d02cb, tablesContext=TablesContext(tables=[Table(name=t_order, alias=null)])))
    Actual SQL: db1 ::: INSERT INTO t_order_202406 (user_id, amount, status, create_time, update_time, order_id) VALUES (?, ?, ?, ?, ?, ?) ::: [123, 999.00, 1, 2024-06-15T10:30:00, 2024-06-15T10:30:00, 1623763800000000001]
    
  2. 直接查询数据库:验证数据是否插入到预期的库表中

6. 高级特性

6.1 读写分离

ShardingSphere支持读写分离,可与分库分表结合使用:

spring:shardingsphere:rules:readwrite-splitting:data-sources:db0:type: Staticprops:write-data-source-name: db0read-data-source-names: db0_slave1,db0_slave2load-balancer-name: round_robindb1:type: Staticprops:write-data-source-name: db1read-data-source-names: db1_slave1,db1_slave2load-balancer-name: round_robinload-balancers:round_robin:type: ROUND_ROBIN

6.2 分布式事务

结合Seata实现分布式事务:

spring:shardingsphere:rules:transaction:default-type: XAprovider-type: Seata

6.3 数据加密

对敏感数据进行加密存储:

spring:shardingsphere:rules:encryption:encryptors:aes_encryptor:type: AESprops:aes-key-value: 123456abcdeftables:t_user:columns:phone:cipher-column: phone_cipherencryptor-name: aes_encryptor

7. 注意事项与最佳实践

7.1 分片键选择

  • 选择频繁作为查询条件的字段作为分片键
  • 避免使用会频繁变更的字段作为分片键
  • 关联表尽量使用相同的分片键,避免跨库关联

7.2 SQL使用限制

  • 避免使用SELECT *,只查询需要的字段
  • 避免复杂的JOIN操作,尤其是跨库JOIN
  • 避免使用ORDER BY、GROUP BY、DISTINCT等操作,可能导致性能问题
  • 分页查询需注意,大量数据的分页可能导致性能问题

7.3 扩容策略

  • 提前规划分片数量,预留扩容空间
  • 采用一致性哈希等算法,减少扩容时的数据迁移量
  • 数据迁移可使用ShardingSphere提供的迁移工具

7.4 监控与运维

  • 集成监控工具,监控各节点性能
  • 定期分析慢查询,优化SQL
  • 制定数据备份与恢复策略

8. 总结

分库分表是解决大数据量存储和高并发访问的有效手段,ShardingSphere作为成熟的中间件解决方案,提供了灵活的分片策略和丰富的功能特性。

本文通过一个完整的电商案例,详细介绍了使用Sharding-JDBC实现多表分库分表的全过程,包括环境准备、策略设计、配置实现、代码开发和测试验证。

在实际应用中,还需要根据业务特点不断优化分片策略,结合读写分离、缓存等技术,构建高性能、高可用的数据库架构。

9. 参考文献

  1. Apache ShardingSphere官方文档:https://shardingsphere.apache.org/
  2. 《ShardingSphere实战》
  3. 《分布式数据库原理与实践》

文章转载自:

http://9KkulDgQ.mqmmc.cn
http://ZBhjAxZ6.mqmmc.cn
http://CNp5L18D.mqmmc.cn
http://EhvIyteL.mqmmc.cn
http://JxAAl04i.mqmmc.cn
http://KQ37IefS.mqmmc.cn
http://yOUcy5kN.mqmmc.cn
http://7nUUpxap.mqmmc.cn
http://BknvkNzP.mqmmc.cn
http://TUj6IICA.mqmmc.cn
http://PgT1ZZOt.mqmmc.cn
http://0lyVxBa2.mqmmc.cn
http://HDp10AQ3.mqmmc.cn
http://YBPBpMcN.mqmmc.cn
http://dd2azYR0.mqmmc.cn
http://GphCdkg5.mqmmc.cn
http://KDkAKGc9.mqmmc.cn
http://Czpwunk3.mqmmc.cn
http://cbwzwXUA.mqmmc.cn
http://IBW0ypCg.mqmmc.cn
http://N0Tfte7o.mqmmc.cn
http://8tPleTCw.mqmmc.cn
http://MX1DbdWn.mqmmc.cn
http://r1PizuY4.mqmmc.cn
http://6cA8n6ue.mqmmc.cn
http://FZXc1LRc.mqmmc.cn
http://X8Nm0LTv.mqmmc.cn
http://ziYse1fv.mqmmc.cn
http://GUY9pEs3.mqmmc.cn
http://ATGxdxrg.mqmmc.cn
http://www.dtcms.com/a/378647.html

相关文章:

  • Docker 部署 MongoDB:单节点与副本集的最佳实践
  • OCR 识别表现好坏离不开什么?
  • 阿里云ACA认证[特殊字符]阿里云ACP认证
  • 计算机网络实验00---环境准备
  • 【路由交换技术】基于eNSP的多子网路由互通实验:从配置到验证的全流程指南
  • 【Python】Python解决阿里云DataWorks导出数据1万条限制的问题
  • 【GMX v1实战】时序风险结算与资本成本:深度解析 GMX 永续合约的资金费率机制
  • axios报错解决:unsupported BodyInit type
  • CRMEB多门店 v3.3源码 无授权限制+PC端+uniapp前端
  • `epoll_event` 结构体解析
  • 《Vuejs设计与实现》第 15 章(编译器核心技术)中
  • C#GDI
  • 智慧工地:科技赋能建筑业高质量发展的新引擎
  • 腾讯云智能体开发平台
  • 多个 Excel 表格如何合并为对应 Sheet 数量的单独 Xlsx 文件
  • 前端-v-model原理
  • 格式刷+快捷键:Excel和WPS表格隔行填充颜色超方便
  • 链表基础与操作全解析
  • GitHub 热榜项目 - 日榜(2025-09-11)
  • 中山GEO哪家好?技术视角解析关键词选词
  • 从零到一上手 Protocol Buffers用 C# 打造可演进的通讯录
  • 当DDoS穿上马甲:CC攻击的本质
  • 【ThreeJs】【自带依赖】Three.js 自带依赖指南
  • STM32短按,长按,按键双击实现
  • Flutter与原生混合开发:实现完美的暗夜模式同步方案
  • AT_abc422_f [ABC422F] Eat and Ride 题解
  • 面试问题详解十八:QT中自定义控件的三种实现方式
  • sql 中的 over() 窗口函数
  • Nginx优化与 SSL/TLS配置
  • Git远程操作(三)