apache.shardingsphere 读写分离、分库分表(后续再完善读写分离+分库分表)

Apache ShardingSphere 分库分表与读写分离实践
本文介绍了如何使用Apache ShardingSphere实现数据库的读写分离和分库分表操作,首先讲解了添加依赖的步骤,接着详细阐述了分库分表的配置和实施过程。

读写分离

#添加依赖


		<dependency>
			<groupId>org.apache.shardingsphere</groupId>
			<artifactId>sharding-jdbc-core</artifactId>
			<version>4.0.0-RC1</version>
		</dependency>

#yml数据库配置(根节点)

database0:
  url: jdbc:mysql://***:3306/srment?characterEncoding=utf8&useSSL=false
  ##数据库database0用户名
  username: srment
  ##数据库database0密码
  password: ***
  ##数据库database0驱动
  driverClassName: com.mysql.cj.jdbc.Driver
  ##数据库database0名称
  databaseName: database0
database1:
  url: jdbc:mysql://***:13306/srment?characterEncoding=utf8&useSSL=false
  ##数据库database1用户名
  username: srment
  ##数据库database1密码
  password: ***
  ##数据库database1驱动
  driverClassName: com.mysql.cj.jdbc.Driver
  ##数据库database1名称
  databaseName: database1


#主库(写)
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

/**
 * 主数据库
 *
 * @author wenrd
 * @date 2020-12-18
 */
@ConfigurationProperties(prefix = "database0")
@Component
public class Database0Config {
    private String url;
    private String username;
    private String password;
    private String driverClassName;
    private String databaseName;

    public DataSource createDataSource() {
        DruidDataSource result = new DruidDataSource();
        result.setDriverClassName(getDriverClassName());
        result.setUrl(getUrl());
        result.setUsername(getUsername());
        result.setPassword(getPassword());
        return result;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getDatabaseName() {
        return databaseName;
    }

    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }
}

#从库(读)

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

/**
 * @author wenrd
 * @date 2020/12/18
 */
@ConfigurationProperties(prefix = "database1")
@Component
public class Database1Config {
    private String url;
    private String username;
    private String password;
    private String driverClassName;
    private String databaseName;

    public DataSource createDataSource() {
        DruidDataSource result = new DruidDataSource();
        r
<think> 我们是在讨论Jeecg-Boot 2.2单体架构下如何配置动态数据源以及ShardingSphere实现读写分离。 注意:Jeecg-Boot本身已经集成了多数据源(dynamic-datasource),而ShardingSphere也是一个强大的数据分片和读写分离框架。但是,两者同时使用可能会有冲突,因为两者都是对数据源进行代理。因此,我们需要考虑整合方案。 通常,有两种思路: 1. 使用ShardingSphere读写分离功能,并关闭Jeecg-Boot的多数据源(或者将ShardingSphere作为唯一数据源,然后由ShardingSphere来管理多个数据源)。 2. 使用Jeecg-Boot的多数据源来管理多个数据源,然后通过AOP等方式实现读写分离(但这样需要自己实现读写分离逻辑,不如ShardingSphere强大)。 这里我们选择第一种方式,即使用ShardingSphere来接管数据源,实现读写分离。而Jeecg-Boot的多数据源功能我们将不使用(或者只使用一个主数据源,这个主数据源就是ShardingSphere的数据源代理)。 具体步骤: 1. 添加ShardingSphere依赖(注意版本兼容性,Jeecg-Boot 2.2使用的是Spring Boot 2.2.x,因此需要选择兼容的ShardingSphere版本,例如4.x版本)。 2. 配置ShardingSphere数据源(包括主库和从库,以及读写分离规则)。 3. 由于Jeecg-Boot默认使用dynamic-datasource,我们需要排除其自动配置,或者覆盖其数据源为ShardingSphere的数据源。 详细步骤: 步骤1:排除dynamic-datasource的自动配置(可选,如果我们不使用它的话) 在application.yml中,我们可以设置spring.autoconfigure.exclude来排除多数据源自动配置类。 步骤2:引入ShardingSphere依赖(以sharding-jdbc-spring-boot-starter为例) 在pom.xml中添加: ```xml <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> <!-- 请根据实际情况选择版本 --> </dependency> ``` 步骤3:配置ShardingSphere读写分离 在application.yml中配置: ```yaml spring: shardingsphere: datasource: names: master,slave0 # 数据源名称,多个用逗号隔开 master: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://主库地址:端口/数据库名?useUnicode=true&characterEncoding=UTF-8&useSSL=false username: 用户名 password: 密码 slave0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://从库地址:端口/数据库名?useUnicode=true&characterEncoding=UTF-8&useSSL=false username: 用户名 password: 密码 masterslave: # 读写分离配置 load-balance-algorithm-type: round_robin # 负载均衡算法类型,可选:round_robin, random name: ms # 主从数据源的名称,可以任意 master-data-source-name: master # 主库数据源名称 slave-data-source-names: slave0 # 从库数据源名称列表,多个用逗号分隔 props: sql: show: true # 是否打印SQL ``` 步骤4:排除Jeecg-Boot的多数据源自动配置 在启动类上排除DynamicDataSourceAutoConfiguration: ```java @SpringBootApplication(exclude = {DynamicDataSourceAutoConfiguration.class}) public class JeecgApplication { public static void main(String[] args) { SpringApplication.run(JeecgApplication.class, args); } } ``` 这样,我们就将数据源交给了ShardingSphere管理,实现了读写分离。 注意:如果项目中使用了分布式事务,那么还需要考虑分布式事务的整合,例如使用Seata。ShardingSphere本身也支持XA和Seata等分布式事务。 然而,以上配置只是实现了读写分离,并没有使用ShardingSphere分库分表功能。如果只需要读写分离,那么以上配置即可。 问题原因:因为Jeecg-Boot默认启用了dynamic-datasource,所以我们需要排除它,否则会出现两个数据源代理,导致冲突。 另外,如果项目中有多个从库,可以配置多个slave数据源,并在slave-data-source-names中用逗号分隔,然后配置负载均衡策略。 但请注意:ShardingSphere读写分离默认情况下,写操作只能发生在主库,读操作在从库(轮询或随机)。如果有些读操作强制需要走主库,可以使用HintManager强制路由到主库。 示例代码(强制走主库): ```java try (HintManager hintManager = HintManager.getInstance()) { hintManager.setMasterRouteOnly(); // 执行查询操作,将强制走主库 ... } ``` 最后,我们给出一个相关问题列表: §§相关问题§§: 1.ShardingSphere中,如何配置多个从库并实现负载均衡? 2. 在使用ShardingSphere实现读写分离时,如何强制某些读操作走主库? 3. Jeecg-Boot排除多数据源自动配置后,原来的多数据源功能还能使用吗? 4. 如何整合ShardingSphere和Seata实现分布式事务? </think> 在Jeecg-Boot 2.2单体架构中整合动态数据源与ShardingSphere实现读写分离,需通过以下步骤配置: ### 1. **依赖配置** 在`pom.xml`中添加ShardingSphere依赖: ```xml <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> <!-- 兼容Spring Boot 2.2.x的版本 --> </dependency> ``` ### 2. **主配置文件(application.yml)** 配置主从数据源和读写分离规则: ```yaml spring: shardingsphere: datasource: names: master,slave0 # 数据源名称 # 主库配置 master: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://主库IP:3306/jeecg-boot?useSSL=false username: master_user password: master_password # 从库配置 slave0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://从库IP:3306/jeecg-boot?useSSL=false username: slave_user password: slave_password masterslave: name: ms # 读写分离规则名称 master-data-source-name: master # 主库标识 slave-data-source-names: slave0 # 从库标识(多个用逗号分隔) load-balance-algorithm-type: round_robin # 从库负载均衡策略 props: sql.show: true # 打印SQL日志(调试用) ``` ### 3. **禁用Jeecg默认多数据源** 在启动类中排除Jeecg的动态数据源自动配置: ```java @SpringBootApplication(exclude = { DynamicDataSourceAutoConfiguration.class // 禁用Jeecg动态数据源 }) public class JeecgApplication { public static void main(String[] args) { SpringApplication.run(JeecgApplication.class, args); } } ``` --- ### **问题原因与解决方案** #### **Q: 为何需要排除`DynamicDataSourceAutoConfiguration`?** - **原因**:Jeecg-Boot默认启用`dynamic-datasource`组件,它会创建自己的动态数据源路由逻辑,与ShardingSphere的数据源代理冲突。 - **解决**:通过`exclude`移除Jeecg的多数据源配置,让ShardingSphere完全接管数据源路由。 #### **Q: 读写分离如何生效?** - **原理**:ShardingSphere通过AOP拦截SQL: - `INSERT/UPDATE/DELETE` 路由到主库 - `SELECT` 路由到从库(轮询负载均衡) - **验证**:观察日志中SQL执行的数据库名称(如`master`/`slave0`)。 #### **Q: 强制读主库的场景?** 使用`HintManager`强制路由到主库: ```java try (HintManager hintManager = HintManager.getInstance()) { hintManager.setMasterRouteOnly(); // 强制后续操作走主库 userService.getUserById(1); // 该方法会从主库读取 } ``` --- ### **注意事项** 1. **版本兼容性**:确保ShardingSphere版本与Spring Boot 2.2.x兼容(推荐4.1.x)。 2. **事务一致性**:跨主从库的写后读操作需添加`@Transactional`注解,确保同一事务内读操作走主库。 3. **从库延迟**:异步复制可能导致刚写入的数据在从库查不到,业务需容忍短暂不一致。 --- ### **完整代码结构** ``` src/main/java ├── com.jeecg │ ├── config │ │ └── ShardingSphereConfig.java // 可选:自定义分片规则 │ ├── Application.java // 启动类(已排除DynamicDataSourceAutoConfiguration) │ └── service │ └── UserService.java // 业务层(无需修改) resources └── application.yml // 配置读写分离规则 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值