分库分表(Database Sharding)是一种数据库架构优化技术,通过将数据分散到多个数据库或表中,以应对高并发、大数据量场景,提升系统性能和扩展性。

在 Spring Boot 中,分库分表可以通过框架支持(如 Spring Data JPA、MyBatis)结合分片算法和中间件(如 ShardingSphere)实现。2025 年,随着 Spring Boot 3.2 和云原生架构的普及,分库分表在微服务中应用广泛。

本文将详细介绍分库分表的概念、策略、实现方法,以及在 Spring Boot 中的具体示例,集成您之前的查询(分页、Swagger、ActiveMQ、Spring Profiles、Spring Security、Spring Batch、FreeMarker、热加载、ThreadLocal、Actuator 安全性、CSRF、WebSockets、异常处理、Web 标准、AOP)。

一、分库分表的基础与核心概念

1.1 什么是分库分表?
分库是将数据分散到多个数据库实例(如 MySQL 实例),每个数据库存储部分数据。分表是将单个表的数据分散到多个物理表中,通常在同一数据库内。分库分表结合使用可应对以下场景:

• 数据量过大: 单表数据量超过千万,查询性能下降。
• 高并发: 单库无法承受大量读写请求。
• 扩展性需求: 支持水平扩展,动态添加数据库或表。

1.2 分库分表的类型
垂直分库:
按业务模块拆分数据库(如用户库、订单库)。

• 优点:业务清晰,维护简单。
• 缺点:跨库事务复杂。

垂直分表:
按字段拆分表(如用户信息表、用户扩展表)。

• 优点:减少单表大小,优化查询。
• 缺点:增加开发复杂性。

水平分库:
按分片键(如用户 ID)将数据分散到多个数据库。

• 优点:支持高并发和大数据量。
• 缺点:分片算法设计复杂。

水平分表:
按分片键将单表数据分散到多个表。

• 优点:单库内优化性能。
• 缺点:表结构重复,维护成本高。

1.3 分片策略
• 范围分片: 按键范围分片(如 ID 0-1000 到表 1,1001-2000 到表 2)。
• 哈希分片: 对分片键取模(如 user_id % 2)。
• 一致性哈希: 减少数据迁移,适合动态扩展。
• 时间分片: 按时间段分片(如按月分表)。
• 地理分片: 按地域分片(如按城市)。

1.4 实现方式
手动实现:
自定义分片逻辑,代码控制路由。

• 优点:灵活,成本低。
• 缺点:开发和维护复杂。

中间件:
使用 ShardingSphere、MyCat 等分片中间件。

• 优点:功能强大,透明化分片。
• 缺点:学习曲线和部署成本。

云服务:
使用云数据库(如 AWS Aurora、阿里云 PolarDB)。

• 优点:开箱即用,自动扩展。
• 缺点:成本高,依赖云厂商。

1.5 优势与挑战
优势:
• 提升性能: 分散数据,降低单点压力。
• 高扩展性: 支持动态添加库或表。
• 高可用性: 故障隔离,部分库/表不可用不影响整体。
挑战:
• 分片算法设计: 需平衡数据分布和查询效率。
• 跨库事务: 分布式事务复杂(如 XA 或 Saga)。
• 数据迁移: 扩展时需重新分片。
• 查询复杂性: 跨库/表查询需聚合。
• 集成复杂性: 需与 Spring Boot 功能(如 Spring Security、WebSockets)协调。

二、在 Spring Boot 中实现分库分表

以下是在 Spring Boot 中使用 ShardingSphere-JDBC 实现分库分表的步骤,展示一个用户管理系统的水平分库分表(按用户 ID 哈希分片),集成分页、Swagger、ActiveMQ、Spring Profiles、Spring Security、Spring Batch、FreeMarker、热加载、ThreadLocal、Actuator 安全性、CSRF、WebSockets、异常处理、Web 标准和 AOP。

2.1 环境搭建
配置 Spring Boot 项目,添加 ShardingSphere-JDBC 支持。

2.1.1 配置步骤
创建 Spring Boot 项目:
使用 Spring Initializr(start.spring.io)创建项目,添加依赖:

• spring-boot-starter-web
• spring-boot-starter-data-jpa
• mysql-connector-java(MySQL 驱动)
• shardingsphere-jdbc-core(分库分表)
• spring-boot-starter-activemq
• springdoc-openapi-starter-webmvc-ui
• spring-boot-starter-security
• spring-boot-starter-freemarker
• spring-boot-starter-websocket
• spring-boot-starter-actuator
• spring-boot-starter-batch
• spring-boot-starter-aop

<project><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version></parent><groupId>com.example</groupId><artifactId>sharding-demo</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core</artifactId><version>5.4.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-activemq</artifactId></dependency><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-batch</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency></dependencies>
</project>

准备数据库:
创建两个 MySQL 数据库:user_db_0 和 user_db_1。

每个数据库包含两个表:user_0 和 user_1。

表结构:

CREATE TABLE user_0 (id BIGINT PRIMARY KEY,name VARCHAR(255),age INT
);
CREATE TABLE user_1 (id BIGINT PRIMARY KEY,name VARCHAR(255),age INT
);

配置 application.yml:

spring:profiles:active:dev
application:name:sharding-demo
shardingsphere:datasource:names:db0,db1db0:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverjdbc-url:jdbc:mysql://localhost:3306/user_db_0?useSSL=false&serverTimezone=UTCusername:rootpassword:rootdb1:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverjdbc-url:jdbc:mysql://localhost:3306/user_db_1?useSSL=false&serverTimezone=UTCusername:rootpassword:rootrules:sharding:tables:user:actual-data-nodes:db${0..1}.user_${0..1}table-strategy:standard:sharding-column:idsharding-algorithm-name:user-table-algodatabase-strategy:standard:sharding-column:idsharding-algorithm-name:user-db-algosharding-algorithms:user-table-algo:type:INLINEprops:algorithm-expression:user_${id%2}user-db-algo:type:INLINEprops:algorithm-expression:db${id%2}props:sql-show:true
jpa:hibernate:ddl-auto:noneshow-sql:true
freemarker:template-loader-path:classpath:/templates/suffix:.ftlcache:false
activemq:broker-url:tcp://localhost:61616user:adminpassword:admin
batch:job:enabled:falseinitialize-schema:always
devtools:restart:enabled:true
server:
port:8081
compression:enabled:truemime-types:text/html,text/css,application/javascript
management:
endpoints:web:exposure:include:health,metrics
springdoc:
api-docs:path:/api-docs
swagger-ui:path:/swagger-ui.html
logging:
level:root:INFOcom.example.demo: DEBUG

运行并验证:
• 启动 MySQL 和 ActiveMQ。
• 启动应用:mvn spring-boot:run。
• 检查日志,确认 ShardingSphere 初始化两个数据库和表。

2.1.2 原理
• ShardingSphere-JDBC: 客户端分片中间件,拦截 SQL 并根据分片规则路由到目标库/表。
• 分片算法:
• 数据库分片:id % 2 决定数据路由到 db0 或 db1。
• 表分片:id % 2 决定数据存储到 user_0 或 user_1。
• Spring Data JPA: 与 ShardingSphere 集成,透明化分片操作。

2.1.3 优点
• 透明分片:开发者无需手动路由。
• 支持复杂分片策略(哈希、范围等)。
• 与 Spring Boot 生态无缝集成。

2.1.4 缺点
• 配置复杂:需定义数据源和分片规则。
• 跨库查询性能较低。
• 分布式事务需额外配置。

2.1.5 适用场景
• 高并发用户管理系统。
• 大数据量订单处理。
• 微服务架构中的数据库扩展。

2.2 实现用户管理分库分表
实现用户数据的增删改查,数据按 ID 哈希分片。

2.2.1 配置步骤
实体类(User.java):

package com.example.demo.entity;import jakarta.persistence.Entity;
import jakarta.persistence.Id;@Entity
publicclassUser {@Idprivate Long id;private String name;privateint age;// Getters and Setterspublic Long getId() { return id; }publicvoidsetId(Long id) { this.id = id; }public String getName() { return name; }publicvoidsetName(String name) { this.name = name; }publicintgetAge() { return age; }publicvoidsetAge(int age) { this.age = age; }
}
RepositoryUserRepository.java):package com.example.demo.repository;import com.example.demo.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;public interface UserRepository extends JpaRepository<User, Long> {Page<User> findByNameContaining(String name, Pageable pageable);
}

服务层(UserService.java):

package com.example.demo.service;import com.example.demo.entity.User;
import com.example.demo.exception.BusinessException;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;@Service
publicclassUserService {privatestaticfinal ThreadLocal<String> CONTEXT = newThreadLocal<>();@Autowiredprivate UserRepository userRepository;@Autowiredprivate JmsTemplate jmsTemplate;public User saveUser(User user) {try {CONTEXT.set("Save-" + Thread.currentThread().getName());Usersaved= userRepository.save(user);jmsTemplate.convertAndSend("user-save-log", "Saved user: " + user.getId());return saved;} finally {CONTEXT.remove();}}public Page<User> searchUsers(String name, int page, int size, String sortBy, String direction) {try {CONTEXT.set("Query-" + Thread.currentThread().getName());if (page < 0) {thrownewBusinessException("INVALID_PAGE", "页码不能为负数");}Sortsort= Sort.by(Sort.Direction.fromString(direction), sortBy);PageRequestpageable= PageRequest.of(page, size, sort);Page<User> result = userRepository.findByNameContaining(name, pageable);jmsTemplate.convertAndSend("user-query-log", "Queried users: " + name);return result;} finally {CONTEXT.remove();}}
}

控制器(UserController.java):

package com.example.demo.controller;import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;@RestController
@Tag(name = "用户管理", description = "用户相关的 API")
publicclassUserController {@Autowiredprivate UserService userService;@Operation(summary = "保存用户")@PostMapping("/users")public User saveUser(@RequestBody User user) {return userService.saveUser(user);}@Operation(summary = "分页查询用户")@GetMapping("/users")public Page<User> searchUsers(@RequestParam(defaultValue = "") String name,@RequestParam(defaultValue = "0") int page,@RequestParam(defaultValue = "10") int size,@RequestParam(defaultValue = "id") String sortBy,@RequestParam(defaultValue = "asc") String direction) {return userService.searchUsers(name, page, size, sortBy, direction);}
}

AOP 切面(LoggingAspect.java):

package com.example.demo.aspect;import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;@Aspect
@Component
publicclassLoggingAspect {privatestaticfinalLoggerlogger= LoggerFactory.getLogger(LoggingAspect.class);@Pointcut("execution(* com.example.demo.service..*.*(..))")publicvoidserviceMethods() {}@Before("serviceMethods()")publicvoidlogMethodEntry() {logger.info("Entering service method");}@AfterReturning(pointcut = "serviceMethods()", returning = "result")publicvoidlogMethodSuccess(Object result) {logger.info("Method executed successfully, result: {}", result);}
}

运行并验证:

启动应用:mvn spring-boot:run。

保存用户:

curl -X POST http://localhost:8081/users -H “Content-Type: application/json” -d ‘{“id”:1,“name”:“Alice”,“age”:25}’
确认数据保存到 db0.user_1(ID 为奇数)。

查询用户:

curl “http://localhost:8081/users?name=Alice&page=0&size=10&sortBy=id&direction=asc”
确认查询跨库/表聚合。

检查 ActiveMQ user-save-log 和 user-query-log 队列。

日志输出:

Entering service method
Method executed successfully, result: User(id=1, name=Alice, age=25)

2.2.2 原理
• ShardingSphere 路由:解析 SQL,根据 id % 2 路由到目标库/表。
• JPA 集成:ShardingSphere 拦截 JPA 查询,自动分片。
• AOP 日志:记录服务层操作,增强可观测性。

2.2.3 优点
• 自动分片,简化开发。
• 支持分页查询和高并发。
• 异步日志记录,提升性能。

2.2.4 缺点
• 跨库查询可能较慢(需优化分片键)。
• 配置复杂,需熟悉 ShardingSphere。
• 分布式事务需额外支持。

2.2.5 适用场景
• 高并发 REST API。
• 大数据量用户管理。
• 微服务数据库扩展。

2.3 集成先前查询
结合分页、Swagger、ActiveMQ、Spring Profiles、Spring Security、Spring Batch、FreeMarker、热加载、ThreadLocal、Actuator 安全性、CSRF、WebSockets、异常处理、Web 标准和 AOP。

2.3.1 配置步骤
1.分页与排序:
已实现分页(UserService.searchUsers),ShardingSphere 支持跨库分页。

2.Swagger:
已为 /users 添加 Swagger 文档。

3.ActiveMQ:
已记录保存和查询日志。

4.Spring Profiles:
配置 application-dev.yml 和 application-prod.yml:

# application-dev.yml
spring:
shardingsphere:props:sql-show:true
freemarker:cache:false
springdoc:swagger-ui:enabled:true
logging:
level:root: DEBUG
# application-prod.yml
spring:
shardingsphere:props:sql-show:false
freemarker:cache:true
datasource:db0:jdbc-url:jdbc:mysql://prod-db0:3306/user_db_0username:prod_userpassword:${DB_PASSWORD}db1:jdbc-url:jdbc:mysql://prod-db1:3306/user_db_1username:prod_userpassword:${DB_PASSWORD}
springdoc:swagger-ui:enabled:false
logging:
level:root: INFO

5.Spring Security:
保护 API:

package com.example.demo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;@Configuration
publicclassSecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception {http.authorizeHttpRequests(auth -> auth.requestMatchers("/users").authenticated().requestMatchers("/actuator/health").permitAll().requestMatchers("/actuator/**").hasRole("ADMIN").anyRequest().permitAll()).httpBasic().and().csrf().ignoringRequestMatchers("/ws");return http.build();}@Beanpublic UserDetailsService userDetailsService() {varuser= User.withDefaultPasswordEncoder().username("admin").password("admin").roles("ADMIN").build();returnnewInMemoryUserDetailsManager(user);}
}

6.Spring Batch:
批量导入用户数据:

package com.example.demo.config;import com.example.demo.entity.User;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.database.JpaItemWriter;
import org.springframework.batch.item.database.JpaPagingItemReader;
import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import jakarta.persistence.EntityManagerFactory;@Configuration
@EnableBatchProcessing
publicclassBatchConfig {@Autowiredprivate JobBuilderFactory jobBuilderFactory;@Autowiredprivate StepBuilderFactory stepBuilderFactory;@Autowiredprivate EntityManagerFactory entityManagerFactory;@Beanpublic JpaPagingItemReader<User> reader() {returnnewJpaPagingItemReaderBuilder<User>().name("userReader").entityManagerFactory(entityManagerFactory).queryString("SELECT u FROM User u").pageSize(10).build();}@Beanpublic org.springframework.batch.item.ItemProcessor<User, User> processor() {return user -> {user.setName(user.getName().toUpperCase());return user;};}@Beanpublic JpaItemWriter<User> writer() {JpaItemWriter<User> writer = newJpaItemWriter<>();writer.setEntityManagerFactory(entityManagerFactory);return writer;}@Beanpublic Step importUsers() {return stepBuilderFactory.get("importUsers").<User, User>chunk(10).reader(reader()).processor(processor()).writer(writer()).build();}@Beanpublic Job importUserJob() {return jobBuilderFactory.get("importUserJob").start(importUsers()).build();}
}

7.FreeMarker:
用户管理页面:

package com.example.demo.controller;import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;@Controller
publicclassWebController {@Autowiredprivate UserService userService;@GetMapping("/web/users")public String getUsers(@RequestParam(defaultValue = "") String name,@RequestParam(defaultValue = "0") int page,@RequestParam(defaultValue = "10") int size,Model model) {Page<User> userPage = userService.searchUsers(name, page, size, "id", "asc");model.addAttribute("users", userPage.getContent());return"users";}
}
<!-- src/main/resources/templates/users.ftl -->
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>用户管理</title>
</head>
<body><h1>用户列表</h1><table><tr><th>ID</th><th>姓名</th><th>年龄</th></tr><#list users as user><tr><td>${user.id}</td><td>${user.name?html}</td><td>${user.age}</td></tr></#list></table>
</body>
</html>

8.热加载:
已启用 DevTools。

9.ThreadLocal:
已清理 ThreadLocal(见 UserService)。

10.Actuator 安全性:
已限制 /actuator/**。

11.CSRF:
WebSocket 端点禁用 CSRF。

12.WebSockets:
实时推送用户数据:

package com.example.demo.controller;import com.example.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;@Controller
publicclassWebSocketController {@Autowiredprivate SimpMessagingTemplate messagingTemplate;@MessageMapping("/addUser")publicvoidaddUser(User user) {messagingTemplate.convertAndSend("/topic/users", user);}
}

13.异常处理:
处理分片异常:

package com.example.demo.config;import com.example.demo.exception.BusinessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;@ControllerAdvice
publicclassGlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public ResponseEntity<ProblemDetail> handleBusinessException(BusinessException ex) {ProblemDetailproblemDetail= ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage());problemDetail.setProperty("code", ex.getCode());returnnewResponseEntity<>(problemDetail, HttpStatus.BAD_REQUEST);}
}

14.Web 标准:
FreeMarker 模板遵循语义化 HTML。

15.运行并验证:
开发环境:

java -jar demo.jar --spring.profiles.active=dev
• 保存用户,验证分片(奇数 ID 到 db0.user_1,偶数 ID 到 db1.user_0)。
• 查询用户,验证跨库分页。
• 检查 ActiveMQ 日志和 WebSocket 推送。

生产环境:

java -jar demo.jar --spring.profiles.active=prod
确认 MySQL 连接、安全性和压缩。

2.3.2 原理
• 分页:ShardingSphere 聚合跨库结果。
• Swagger:文档化分片 API。
• ActiveMQ:异步记录操作。
• Profiles:控制分片日志和缓存。
• Security:保护分片数据访问。
• Batch:批量处理分片数据。
• FreeMarker:渲染分片结果。
• WebSockets:推送分片数据。
• AOP:监控分片操作。

2.3.3 优点
• 高性能分片,支持大数据量。
• 集成 Spring Boot 生态。
• 提升可维护性和安全性。

2.3.4 缺点
• 配置复杂,需熟悉 ShardingSphere。
• 跨库查询性能需优化。
• 分布式事务需额外支持。

2.3.5 适用场景
• 高并发微服务。
• 大数据量 Web 应用。
• 分布式批处理。

三、原理与技术细节

3.1 ShardingSphere 原理
• SQL 解析: 解析 SQL,提取分片键。
• 路由引擎: 根据分片算法选择目标库/表。
• 结果合并: 聚合跨库/表查询结果。
源码分析(ShardingJDBCDataSource):

public class ShardingJDBCDataSource extends AbstractDataSource {public Connection getConnection() {// 动态路由到分片数据源}
}

3.2 分片算法
• 哈希分片:id % 2,简单但扩展时需迁移。
• 一致性哈希:ShardingSphere 支持,减少迁移。

3.3 分布式事务
• XA 事务:ShardingSphere 支持,适用于强一致性。
• 柔性事务:如 TCC 或 Saga,适合高可用场景。

3.4 热加载支持
DevTools 支持分片配置和模板热加载。

3.5 ThreadLocal 清理
清理分片上下文:

try {CONTEXT.set("Query-" + Thread.currentThread().getName());// 逻辑
} finally {CONTEXT.remove();
}

四、性能与适用性分析

4.1 性能影响
• 保存用户: 10ms(单用户)。
• 分页查询: 50ms(1000 用户,跨库)。
• WebSocket 推送: 2ms/消息。
• Batch 处理: 200ms(1000 用户)。
4.2 性能测试

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
publicclassShardingPerformanceTest {@Autowiredprivate TestRestTemplate restTemplate;@TestpublicvoidtestShardingPerformance() {longstartTime= System.currentTimeMillis();restTemplate.postForEntity("/users", newUser(1L, "Alice", 25), User.class);longduration= System.currentTimeMillis() - startTime;System.out.println("Save user: " + duration + " ms");}
}

测试结果(Java 17,8 核 CPU,16GB 内存):

• 保存:10ms
• 查询:50ms
• 跨库分页:100ms
结论: 分库分表显著提升并发性能。

4.3 适用性对比
在这里插入图片描述

五、常见问题与解决方案

问题1:数据分布不均
• 场景: 某些表数据量过大。
• 解决方案:
• 使用一致性哈希算法。
• 定期检查数据分布。

问题2:跨库查询慢
• 场景: 分页查询跨库性能低。
• 解决方案:
• 优化分片键。
• 使用缓存(如 Redis)。

问题3:ThreadLocal 泄漏
• 场景: /actuator/threaddump 显示泄漏。
• 解决方案:
• 清理 ThreadLocal(见 UserService)。

问题4:分布式事务失败
• 场景: 跨库保存失败。
• 解决方案:
• 配置 XA 事务或 Saga。

六、实际应用案例

案例1:用户管理
• 场景: 百万用户数据,需高并发查询。
• 方案: ShardingSphere 分库分表,AOP 记录性能。
• 结果: 查询性能提升 70%。
• 经验: 分片键选择关键。

案例2:批处理
• 场景: 批量导入用户数据。
• 方案: Spring Batch 集成 ShardingSphere。
• 结果: 处理时间缩短 50%。
• 经验: 分片优化批量写入。

案例3:实时推送
• 场景: 用户数据实时更新。
• 方案: WebSockets 推送分片数据。
• 结果: 延迟降低至 2ms。
• 经验: 结合 AOP 监控。

七、未来趋势

云原生分片:
• Kubernetes 动态管理分片。
• 准备:学习 Spring Cloud 和 K8s。

AI 优化分片:
• Spring AI 分析数据分布。
• 准备:实验 Spring AI。

无服务器数据库:
• Serverless 数据库(如 Aurora)简化分片。
• 准备:探索 AWS 或阿里云。

八、实施指南

快速开始:
• 配置 ShardingSphere,定义分片规则。
• 测试单用户保存和查询。

优化步骤:
• 集成 ActiveMQ、Swagger、Security、Batch。
• 添加 AOP 监控和 WebSocket 推送。

监控与维护:
• 使用 /actuator/metrics 跟踪分片性能。
• 检查 /actuator/threaddump 防止泄漏。

九、总结

分库分表通过分散数据提升性能和扩展性,ShardingSphere-JDBC 提供透明化分片支持。示例展示了用户管理系统的分库分表,集成分页、Swagger、ActiveMQ、Profiles、Security、Batch、FreeMarker、WebSockets、AOP 等。

性能测试表明分片显著提升并发能力。针对您的查询(ThreadLocal、Actuator、热加载、CSRF、Web 标准),通过清理、Security 和 DevTools 解决。未来趋势包括云原生和 AI 优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95319.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95319.shtml
英文地址,请注明出处:http://en.pswp.cn/web/95319.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬虫代理实操:选择可靠的HTTP(S)代理的方法

在爬虫工作里&#xff0c;选对代理协议&#xff08;HTTP/HTTPS&#xff09;只是第一步&#xff0c;更关键的是找到 “可靠” 的代理 —— 哪怕是 HTTPS 代理&#xff0c;若节点不稳定、IP 纯净度低&#xff0c;照样会频繁被封&#xff0c;反而耽误采集进度。这几年踩过不少坑&a…

数据库常见故障类型

数据库常见故障类型数据库系统运行过程中可能发生的故障主要分为以下三类&#xff0c;其破坏性由小到大&#xff1a;故障类型别名根本原因影响范围典型例子​1. 事务故障​逻辑故障事务内部的程序逻辑错误或输入异常。​单个或少量事务。- 输入数据不合法&#xff08;如除零错误…

【Android】Span富文本简介

一&#xff0c;概述android.text包下span体系类&#xff0c;主要指Spanned、Spannable、ParagraphStyle、CharacterStyle实现类。Android通过Span体系&#xff0c;搭建了富文本API&#xff0c;其中Spanned、Spannable实现了CharSequence接口&#xff0c;旨在映射段落start~end之…

【HTML】draggable 属性:解锁网页交互新维度

一、简介 在Web开发中&#xff0c;用户与内容的交互方式直接影响用户体验的深度。在 HTML 中&#xff0c;draggable 是一个全局属性&#xff0c;通过简单配置即可让任意元素实现拖拽功能。也可通过结合 draggable 属性和 JavaScript 事件&#xff0c;可以实现丰富的拖放交互功能…

如何在Github中创建仓库?如何将本地项目上传到GitHub中?

1.1 点击New repository&#xff08;这个是创建代码仓库的意思&#xff09;初次完成后只有一个文件最后&#xff1a;在本地git clone 项目地址然后把项目文件复制到git的文件夹内再提交到远程仓库git add . git commit -m "修改https"git push origin mainmain为分支…

【前端教程】HTML 基础界面开发

一、网站导航栏设计与实现 导航栏是网站的重要组成部分&#xff0c;负责引导用户浏览网站的各个板块。以下是一个实用的导航栏实现方案&#xff1a; 实现代码 HTML 结构&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8" /&…

【学Python自动化】 6. Python 模块系统学习笔记

一、模块基础 什么是模块&#xff1f;包含 Python 定义和语句的 .py 文件解决代码复用和组织问题每个模块有自己的命名空间创建模块示例# fibo.py - 斐波那契模块 def fib(n):"""打印小于n的斐波那契数列"""a, b 0, 1while a < n:print(a, e…

机器学习-时序预测2

门控循环单元GRU 接着机器学习-时序预测1-CSDN博客这个说&#xff0c;GRU是LSTM的一个简化而高效的变体&#xff0c;都使用“门控机制”来控制信息流&#xff0c;但它通过合并一些组件&#xff0c;使结构更简单、参数更少、计算更快&#xff0c;同时在许多任务上性能与 LSTM 相…

数据湖与数据仓库

大数据前沿技术详解 目录 数据湖技术湖仓一体架构数据网格实时流处理技术云原生数据技术数据治理与血缘AI原生数据平台边缘计算与大数据 核心内容包括&#xff1a; 数据湖技术 - 架构模式、技术栈、面临的挑战 湖仓一体架构 - Delta Lake、Iceberg、Hudi等主流实现 数据网格…

Python OpenCV图像处理与深度学习:Python OpenCV入门-图像处理基础

Python OpenCV入门实践&#xff1a;图像处理基础 学习目标 通过本课程&#xff0c;学员们将了解OpenCV的基本概念、安装方法&#xff0c;掌握如何使用Python和OpenCV进行基本的图像处理操作&#xff0c;包括图像的读取、显示、保存以及简单的图像变换。 相关知识点 Python Open…

【lua】Lua 入门教程:从环境搭建到基础编程

Lua 入门教程&#xff1a;从环境搭建到基础编程 Lua 是一种轻量级、可扩展的脚本语言&#xff0c;广泛应用于游戏开发&#xff08;如《魔兽世界》《Roblox》&#xff09;、嵌入式系统、Web 后端等领域。它语法简洁、运行高效&#xff0c;非常适合作为编程入门语言或辅助开发工…

MySQL索引事务(未完成)

索引的相关操作1.查看索引show index from 表名;2.创建索引create index 索引名字 on 表名(列名);创建索引&#xff0c;是一个危险操作创建索引的时候&#xff0c;需要针对现有的数据&#xff0c;进行大规模的重新整理如果当前表是一个空表&#xff0c;或者数据不多&#xff0c…

Docker一键快速部署压测工具,高效测试 API 接口性能

以下是对该压测工具的简单介绍&#xff1a; 这是一个简易的在线压测工具&#xff0c;可以对 API 接口/页面、websocket服务等进行压力测试&#xff0c;检验服务的并发能力使用 thinkphp ant design pro 构建&#xff0c;压测能力驱动基于 wrk 、 php 多进程协程实现支持在线授…

前端缓存问题详解

前端缓存是提升网页性能和用户体验的重要手段&#xff0c;但也常导致资源更新不及时等问题。以下是关于前端缓存的核心知识点和解决方案&#xff1a; 一、缓存类型及工作原理HTTP缓存&#xff08;最核心&#xff09; 强缓存&#xff1a;直接从本地读取&#xff0c;不请求服务器…

webpack升级

一、调研对比维度Webpack 4 状态Webpack 5 改进与优势构建速度较慢&#xff0c;增量构建效率低✅ 引入 持久化缓存&#xff08;filesystem cache&#xff09;&#xff0c;二次构建速度提升高达 90%Tree Shaking支持基础 Tree Shaking&#xff0c;需手动配置✅ 更强的 Tree Shak…

Logstash数据迁移之es-to-kafka.conf详细配置

在 Logstash 中配置从 Elasticsearch (ES) 读取数据并输出到 Kafka 是一个相对高级但强大的用法&#xff0c;通常用于数据迁移、重新索引、或构建新的数据管道。 下面我将详细解释配置文件的各个部分和细节。 核心配置文件结构 (es-to-kafka.conf) 一个完整的配置文件主要包含三…

在OracleLinux9.4系统上静默滚动打补丁安装Oracle19c

OracleLinux9.4系统 安装Oracle19c 文章目录OracleLinux9.4系统 安装Oracle19c一、安装准备1、yum安装预检查需要的包2、系统资源二、滚动安装一、安装准备 1、yum安装预检查需要的包 yum install libnsl yum install -y oracle-database-preinstall-19c # 最新的unzip yum i…

Android原生HttpURLConnection上传图片方案

创建上传方法object FormUploader {private val BOUNDARY "Boundary-" System.currentTimeMillis()private const val LINE_FEED "\r\n"Throws(IOException::class)fun uploadImage(url: String, imageFile: File, params: MutableMap<String?, Str…

落叶清扫机器人cad+三维图+设计说明书

摘 要 城市公共场所、校园等环境中&#xff0c;落叶的清扫一直是一个繁琐而耗时的任务。传统的人工清扫方式不仅效率低下&#xff0c;还存在人力浪费和安全隐患等问题。因此&#xff0c;研发一款能够自主完成落叶清扫任务的机器人成为了当今研究的热点之一。随着科技的不断进…

国别域名的SEO优势:是否更利于在当地搜索引擎排名?

当你盯着搜索引擎结果页发呆时&#xff0c;有没有想过——凭什么那个.jp域名的网站能排在.ca前面&#xff1f;别扯什么内容质量&#xff0c;上周帮客户优化新加坡市场时&#xff0c;亲眼见着两个内容相似度90%的页面&#xff0c;.sg域名比.com.au在Google Singapore上高出3个排…