spring boot sharding-jdbc实现分佈式读写分离和分库分表的实现
分布式读写分离和分库分表采用sharding-jdbc实现。
sharding-jdbc是当当网推出的一款读写分离实现插件,其他的还有mycat,或者纯粹的Aop代码控制实现。
接下面用spring boot 2.1.4 release 版本实现读写分离。
1. 引入jar包
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!-- sharding-jdbc -->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>1.5.4</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> 2. 添加配置文件

分别添加三份,配置为database0,database1,database2。
3. 添加DataSourceConfig
package com.fintecher.cn.elasticjobdemo.config; import com.dangdang.ddframe.rdb.sharding.api.ShardingDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.keygen.DefaultKeyGenerator;
import com.dangdang.ddframe.rdb.sharding.keygen.KeyGenerator;
import com.fintecher.cn.elasticjobdemo.service.DatabaseShardingAlgorithm;
import com.fintecher.cn.elasticjobdemo.service.TableShardingAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig { @Autowired
private Database1Config database1Config; @Autowired
private Database2Config database2Config; @Autowired
private DatabaseShardingAlgorithm databaseShardingAlgorithm; @Autowired
private TableShardingAlgorithm tableShardingAlgorithm; @Bean
public DataSource getDataSource() throws SQLException {
return buildDataSource();
} private DataSource buildDataSource() throws SQLException {
//设置从库数据源集合
Map<String, DataSource> slaveDataSourceMap = new HashMap<>();
slaveDataSourceMap.put(database1Config.getDatabaseName(), database1Config.createDataSource());
slaveDataSourceMap.put(database2Config.getDatabaseName(), database2Config.createDataSource()); //设置默认数据库
DataSourceRule dataSourceRule = new DataSourceRule(slaveDataSourceMap, database1Config.getDatabaseName()); //分表设置
TableRule orderTableRules = TableRule.builder("user").actualTables(Arrays.asList("user_0", "user_1")).dataSourceRule(dataSourceRule).build(); //分库分表策略
ShardingRule shardingRule = ShardingRule.builder()
.dataSourceRule(dataSourceRule)
.tableRules(Arrays.asList(orderTableRules))
.databaseShardingStrategy(new DatabaseShardingStrategy("id", databaseShardingAlgorithm))
.tableShardingStrategy(new TableShardingStrategy("name", tableShardingAlgorithm))
.build(); //获取数据源对象
// DataSource dataSource = MasterSlaveDataSourceFactory.createDataSource("masterSlave", database0Config.getDatabaseName()
// , database0Config.createDataSource(), slaveDataSourceMap, MasterSlaveLoadBalanceStrategyType.getDefaultStrategyType()); DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule); return dataSource;
} @Bean
public KeyGenerator keyGenerator() {
return new DefaultKeyGenerator();
} }
4. 分库实现方案
@Component
public class DatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Long> { @Autowired
private Database2Config database2Config; @Autowired
private Database1Config database1Config; @Override
public String doEqualSharding(Collection<String> collection, ShardingValue<Long> shardingValue) {
Long value = shardingValue.getValue();
if (value <= 20L)
return database1Config.getDatabaseName();
else
return database2Config.getDatabaseName();
} @Override
public Collection<String> doInSharding(Collection<String> collection, ShardingValue<Long> shardingValue) {
return null;
} @Override
public Collection<String> doBetweenSharding(Collection<String> collection, ShardingValue<Long> shardingValue) {
return null;
} } 5. 分表实现方案
@Component
public class TableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<String> { @Override
public String doEqualSharding(Collection<String> tableNames, ShardingValue<String> shardingValue) {
for (String each : tableNames) {
if (each.endsWith("0") && shardingValue.getValue().contains("军")) {
return "user_0";
} else
return "user_1";
}
return null;
} @Override
public Collection<String> doInSharding(Collection<String> collection, ShardingValue<String> shardingValue) {
return null;
} @Override
public Collection<String> doBetweenSharding(Collection<String> collection, ShardingValue<String> shardingValue) {
return null;
} }
5. 环境参数配置
#jpa 配置
spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
##数据库database0配置
database0.url=jdbc:mysql://192.168.3.32:3306/database0?characterEncoding=utf8&useSSL=false
database0.username=root
database0.password=123456
database0.driverClassName=com.mysql.jdbc.Driver
database0.databaseName=database0
##数据库database1地址
database1.url=jdbc:mysql://192.168.3.32:3306/database1?characterEncoding=utf8&useSSL=false
database1.username=root
database1.password=123456
database1.driverClassName=com.mysql.jdbc.Driver
database1.databaseName=database1
##数据库database2地址
database2.url=jdbc:mysql://192.168.3.32:3306/database2?characterEncoding=utf8&useSSL=false
database2.username=root
database2.password=123456
database2.driverClassName=com.mysql.jdbc.Driver
database2.databaseName=database2
6. 测试

7. 达到的效果
插入40条数据,20条在base1,20条在base2,base1中张军的数据在user_0,李四的数据在user_1
8. 问题总结:
在写代码的过程中自己引包的时候很随便,引入了一些其他的包,如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.11.18.RELEASE</version>
</dependency>
导致在起服务的时候报 :

解决方案:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
将上面三个包换成这两个即可。
9. 总结
在使用sharding-jdbc过程中实现了
SingleKeyDatabaseShardingAlgorithm 这个接口,这个接口有三个方法 equal,in ,between ,这三个方法的作用是在比较传送过来的值的时候分别用这三种方案进行比较。 10. 遗留问题,当把数据库分库分表存后,查询怎么获取到所有的数据呢。 11. 参考文档:https://yq.aliyun.com/articles/690021https://www.dalaoyang.cn/article/95?spm=a2c4e.11153940.blogcont690021.12.2057195fd9jYc312. 获取数据解决方案:
1. 广发复制法, 比如主表 Personal表,分别存在于多个数据库,关联表 persona_address, 只存在于主服务数据库,这种方式就是在修改了persona_address表之后将这张表再复制一份到从数据库,这样查询的时候从从数据库关联后再汇总查询。
2. 从数据库实时同步主数据库,从主数据库查询。
spring boot sharding-jdbc实现分佈式读写分离和分库分表的实现的更多相关文章
- mycat+mysql集群:实现读写分离,分库分表
1.mycat文档:https://github.com/MyCATApache/Mycat-doc 官方网站:http://www.mycat.org.cn/ 2.mycat的优点: 配 ...
- Mycat数据库中间件对Mysql读写分离和分库分表配置
Mycat是一个开源的分布式数据库系统,不同于oracle和mysql,Mycat并没有存储引擎,但是Mycat实现了mysql协议,前段用户可以把它当做一个Proxy.其核心功能是分表分库,即将一个 ...
- MyCat读写分离、分库分表
系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优化也是非常重要的.主从.热备.分表分库等都是系统发展迟早会遇到的技术问题问题.Mycat是一 ...
- Mycat实现读写分离、分库分表
系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优化也是非常重要的.主从.热备.分表分库等都是系统发展迟早会遇到的技术问题问题.Mycat是一 ...
- sharding demo 读写分离 U (分库分表 & 不分库只分表)
application-sharding.yml sharding: jdbc: datasource: names: ds0,ds1,dsx,dsy ds0: type: com.zaxxer.hi ...
- sharing-jdbc实现读写分离及分库分表
需求: 分库:按业务线business_id将不同业务线的订单存储在不同的数据库上: 分表:按user_id字段将不同用户的订单存储在不同的表上,为方便直接用非分片字段order_id查询,可使用基因 ...
- Mysql之Mycat读写分离及分库分表
## 什么是mycat ```basic 1.一个彻底开源的,面向企业应用开发的大数据库集群 2.支持事务.ACID.可以替代MySQL的加强版数据库 3.一个可以视为MySQL集群的企业级数据库,用 ...
- Ameba读写分离_mycat分库分表_redis缓存
1 数据库的读写分离 1.1 Amoeba实现读写分离 1.1.1 定义 Amoeba是一个以MySQL为底层数据存储,并对应用提供MySQL协议接口的proxy 优点: 配置读写分离时较为简单.配置 ...
- mysql主从读写分离,分库分表
1.分表 当项目上线后,数据将会几何级的增长,当数据很多的时候,读取性能将会下降,更新表数据的时候也需要更新索引,所以我们需要分表,当数据量再大的时候就需要分库了. a.水平拆分:数据分成多个表 b. ...
随机推荐
- python爬虫错误总结
这几天突然想到学习爬虫,于是就从python开始,python教程瞄了两眼,就去网上找别人写的爬虫(爬音乐网站的歌曲) 磕磕绊绊中渐渐地熟悉了python中常用的库和模块. 1.python 2.x( ...
- SOFA 源码分析 — 连接管理器
前言 RPC 框架需要维护客户端和服务端的连接,通常是一个客户端对应多个服务端,而客户端看到的是接口,并不是服务端的地址,服务端地址对于客户端来讲是透明的. 那么,如何实现这样一个 RPC 框架的网络 ...
- php $_SERVER['HTTP_USER_AGENT'] 用法介绍
在PHP中HTTP_USER_AGENT是用来获取用户的相关信息的,包括用户使用的浏览器,操作系统等信息, 显示结果为: Mozilla/5.0 (Windows NT 6.1; WOW64) App ...
- 利用百度地图api实现定位
使用百度地图api前需要先获取一个百度地图开放平台的访问应用AK, 获取百度地图开放平台访问应用AK方式:注册百度账号-->申请百度开发者-->获取密匙-->使用相关功能. 注册账号 ...
- JDK及JRE目录结构
JDK文件结构及目录: c:\jdk1.7.0: JDK安装根目录,包括版权.许可证和READEME文件,还包含ser.zip记录Java平台档案. c:\jdk1.7.0\bin 包含在Java开发 ...
- ThreadPoolExecutor 学习笔记
线程池的奥义 在开发程序的过程中,很多时候我们会遇到遇到批量执行任务的场景,当各个具体任务之间互相独立并不依赖其他任务的时候,我们会考虑使用并发的方式,将各个任务分散到不同的线程中进行执行来提高任务的 ...
- Scala学习笔记:重要语法特性
1.变量声明 Scala 有两种变量, val 和 var val的值声明后不可变,var可变 val msg: String = "Hello yet again, world!&quo ...
- sh 脚本执行sql文件传参数
一.前言 今天做数据删除,用的命令行输入参数,并且调用执行的sql文件,我采用了sed命令,进行替换. sh脚本如下 #! /bin/sh echo "Please enter the ba ...
- java并发之非阻塞算法介绍
在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法.在绝大多数项目中,在算法中如果一个线程的挂起没有导致其它的线程挂起,我们就说这个算法是非阻塞的. 为了更好的理解阻塞算 ...
- Oracle-10:分析函数
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 分析函数: 分析函数,可以修改排序的规则!!!!!!!!!!!!!!!!!!!!!!!! 首先把数据库脚本给放 ...