提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
ShardingSphere-JDBC是一个开源的分布式数据库中间件,提供了数据库的分库分表、读写分离、数据分片等功能。它的主要特点包括:
- 分库分表:可以将数据按照一定规则分散到不同的数据库或表中,实现数据的水平切分,提高数据库的扩展性和性能。
- 读写分离:可以根据需求将读操作和写操作分发到不同的数据库节点,实现读写分离,提高数据库的负载能力。
- 数据分片:可以按照某种特定的规则将数据分散到不同的数据库节点上,并通过统一的接口对外提供访问,实现数据的分布式存储。
- 支持多种数据库:ShardingSphere-JDBC支持多种主流数据库,如MySQL、Oracle、SQL Server等,可以方便地与现有的数据库系统集成。
- 兼容性强:ShardingSphere-JDBC完全兼容现有的JDBC接口和SQL语法,使用方便,对现有的应用程序无需修改或重新编写。
- 高性能:ShardingSphere-JDBC经过优化,具有较好的性能表现,可以提供高并发、低延迟的数据库访问能力。
总之,ShardingSphere-JDBC是一个功能强大的分布式数据库中间件,可以帮助开发人员简化数据库架构设计、提高数据库性能和扩展性,是构建高可用、高性能的分布式系统的理想选择。
提示:以下是本篇文章正文内容,下面案例可供参考
一、内部结构
官方文档链接:ShardingSphere-JDBC
二、配置及使用示例
1.依赖包配置
代码如下(示例):
<!-- Sharding-JDBC核心依赖 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>4.0.1</version>
</dependency>
2.基于Spring boot的规则配置,使用JAVA配置
代码如下(示例):
#sharding.jdbc(读写分离)数据源名称,多数据源以逗号分隔
spring.shardingsphere.datasource.names=master,slave0,slave1
#数据库连接池类名称
spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
#数据库驱动类名(主库)
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.url=jdbc:mysql://172.16.xxx.xx1:3306/test_data?verifyServerCertificate=false&useSSL=false&requireSSL=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=utf8
spring.shardingsphere.datasource.master.username=gfh_dev_1
spring.shardingsphere.datasource.master.password=123456
#以下配置可根据具体情况选择和修改(每个数据源都可配置,该示例从库省略)
spring.shardingsphere.datasource.master.maxActive=300
spring.shardingsphere.datasource.master.maxWait=10000
spring.shardingsphere.datasource.master.minIdle=5
spring.shardingsphere.datasource.master.initialSize=5
spring.shardingsphere.datasource.master.validationQuery=SELECT 1
spring.shardingsphere.datasource.master.testWhileIdle=true
spring.shardingsphere.datasource.master.timeBetweenEvictionRunsMillis=18800
spring.shardingsphere.datasource.master.minEvictableIdleTimeMillis=300000
spring.shardingsphere.datasource.master.removeAbandoned=true
spring.shardingsphere.datasource.master.removeAbandonedTimeoutMillis=300
spring.shardingsphere.datasource.master.filters=stat
#从库1
spring.shardingsphere.datasource.slave0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave0.url=jdbc:mysql://172.16.xxx.xx2:3306/test_data?verifyServerCertificate=false&useSSL=false&requireSSL=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=utf8
spring.shardingsphere.datasource.slave0.username=gfh_dev_2
spring.shardingsphere.datasource.slave0.password=123456
#从库2
spring.shardingsphere.datasource.slave1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave1.url=jdbc:mysql://172.16.xxx.xx3:3306/test_data?verifyServerCertificate=false&useSSL=false&requireSSL=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=utf8
spring.shardingsphere.datasource.slave1.username=gfh_dev_3
spring.shardingsphere.datasource.slave1.password=123456
#从库负载均衡算法类型,可选值:(轮询)round_robin,(随机)random。若`load-balance-algorithm-class-name`存在则忽略该配置
spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
spring.shardingsphere.masterslave.name=dataSource
#主库数据源名称
spring.shardingsphere.masterslave.master-data-source-name=master
#从库数据源名称列表
spring.shardingsphere.masterslave.slave-data-source-names=slave0,slave1
#是否开启SQL显示,默认值: false
spring.shardingsphere.props.sql.show=true
3.使用java代码引用配置文件(则无需其他依赖包)
加载数据源
import com.alibaba.druid.pool.DruidDataSource;
import com.zgf.gongfuhui.backendapi.utils.EncryptUtils;
@SuppressWarnings("serial")
public class SecurityDataSource extends DruidDataSource {
public SecurityDataSource() {
super();
}
@Override
public void setPassword(String password) {
//
String decryptPwd = EncryptUtils.decryptDsPwd(password);
super.setPassword(decryptPwd);
}
}
调用数据源进行读写分离配置
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shardingsphere.api.config.masterslave.LoadBalanceStrategyConfiguration;
import org.apache.shardingsphere.api.config.masterslave.MasterSlaveRuleConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.MasterSlaveDataSourceFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
/**
* @Author: 123
* @Description: shardingJdbc读写分离配置文件
* @Date: 2020/5/21 12:12
*/
@Configuration
@MapperScan(basePackages = {"com.zgf.gongfuhui.backendapi.mapper", "com.zgf.gongfuhui.backendapi.commonMapper"},
sqlSessionTemplateRef = "shardingSqlSessionTemplate")
public class DataSourceConfigRation {
@Value("${spring.shardingsphere.masterslave.name}")
private String name;
@Value("${spring.shardingsphere.masterslave.master-data-source-name}")
private String masterDataSourceName;
@Value("${spring.shardingsphere.masterslave.slave-data-source-names}")
private String slaveDataSourceNames;
@Value("${spring.shardingsphere.masterslave.load-balance-algorithm-type}")
private String type;
@Value("${spring.shardingsphere.props.sql.show}")
private boolean sqlShow;
@Bean(name = "master")
@ConfigurationProperties(prefix = "spring.shardingsphere.datasource.master")
public DataSource master() {
return new SecurityDataSource();
}
@Bean(name = "slave0")
@ConfigurationProperties(prefix = "spring.shardingsphere.datasource.slave0")
public DataSource slave0() {
return new SecurityDataSource();
}
@Bean(name = "slave1")
@ConfigurationProperties(prefix = "spring.shardingsphere.datasource.slave1")
public DataSource slave1() {
return new SecurityDataSource();
}
@Bean(name = "dataSourceMap")
public Map<String, DataSource> dataSourceMap(@Qualifier("master") DataSource master,
@Qualifier("slave0") DataSource slave0, @Qualifier("slave1") DataSource slave1) {
// 设置分库映射
Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
dataSourceMap.put("master", master);
dataSourceMap.put("slave0", slave0);
dataSourceMap.put("slave1", slave1);
// 设置默认库,两个库以上时必须设置默认库。默认库的数据源名称必须是dataSourceMap的key之一
return dataSourceMap;
}
@Bean(name = "shardingDataSource")
public DataSource getShardingDataSource(
@Qualifier("dataSourceMap") Map<String, DataSource> dataSourceMap) throws SQLException {
Properties properties = new Properties();
properties.put("sql.show", sqlShow);
LoadBalanceStrategyConfiguration loadBalanceStrategyConfiguration = new LoadBalanceStrategyConfiguration(type);
MasterSlaveRuleConfiguration masterSlaveRuleConfiguration = new
MasterSlaveRuleConfiguration(name, masterDataSourceName,
Arrays.asList(slaveDataSourceNames.split(",")),
loadBalanceStrategyConfiguration);
//获取数据源对象
return MasterSlaveDataSourceFactory.createDataSource(dataSourceMap, masterSlaveRuleConfiguration, properties);
}
/**
* 需要手动配置事务管理器
*
* @param shardingDataSource
* @return
*/
@Bean
public DataSourceTransactionManager transactitonManager(
@Qualifier("shardingDataSource") DataSource shardingDataSource) {
return new DataSourceTransactionManager(shardingDataSource);
}
@Primary
@Bean(name = "shardingSqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("shardingDataSource") DataSource shardingDataSource)
throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(shardingDataSource);
return sqlSessionFactoryBean.getObject();
}
@Primary
@Bean(name = "shardingSqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("shardingSqlSessionFactory") SqlSessionFactory shardingSqlSessionFactory) {
return new SqlSessionTemplate(shardingSqlSessionFactory);
}
}
三、基于暗示(Hint)的强制主库路由
1.简介
ShardingSphere使用ThreadLocal管理分片键值进行Hint强制路由。可以通过编程的方式向HintManager中添加分片值,该分片值仅在当前线程内生效。 Hint方式主要使用场景:
1.分片字段不存在SQL中、数据库表结构中,而存在于外部业务逻辑。
2.强制在主库进行某些数据操作。
2.获取HintManager设置主库路由
使用hintManager.setMasterRouteOnly设置主库路由。清除分片键值:分片键值保存在ThreadLocal中,所以需要在操作结束时调用hintManager.close()来清除ThreadLocal中的内容。hintManager实现了AutoCloseable接口,可推荐使用try with resource自动关闭。
3. 示例
官方完整代码示例
String sql = "SELECT * FROM t_order";
try (
HintManager hintManager = HintManager.getInstance();
Connection conn = dataSource.getConnection();
PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
hintManager.setMasterRouteOnly();
try (ResultSet rs = preparedStatement.executeQuery()) {
while (rs.next()) {
// ...
}
}
}
可在API头部使用
@RequestMapping(value = "/order/makeOrder", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
public ResponseObject makeOrder() {
try {
// 强制路由到主库
HintManager hintManager = HintManager.getInstance();
hintManager.setMasterRouteOnly();
// 其他逻辑代码块
....
} finally {
// 在finally中强制路由器被释放
hintManager.close();
}
}
总结
使用ShardingSphere-JDBC实现读写分离,需要进行以下步骤:
-
配置数据源:首先,需要配置多个数据源,分别用于处理读操作和写操作。可以使用ShardingSphere提供的多种数据源类型,例如Master-Slave数据源、Sharding数据源等。
-
配置数据源路由:接下来,需要配置数据源的路由规则,以确定读操作和写操作分别路由到哪些数据源上。可以根据业务需求进行灵活的配置,例如根据SQL语句中的表名或列名进行路由。
-
配置读写分离:在配置数据源路由的基础上,还需要配置读写分离规则,将读操作和写操作分别路由到不同的数据源上。可以根据业务需求进行灵活的配置,例如使用主从同步来实现读写分离。
-
配置数据库连接池:最后,需要配置数据库连接池,以提高系统的性能和可扩展性。可以使用ShardingSphere提供的多种连接池技术,例如Druid、HikariCP等。
总结起来,使用ShardingSphere-JDBC实现读写分离需要配置数据源、数据源路由、读写分离规则和数据库连接池。通过合理的配置和路由规则,可以将读操作和写操作分别路由到不同的数据库节点上,以提高系统的性能和可扩展性。同时,使用数据库连接池可以进一步提高系统的性能和可靠性。