1.引入maven依赖:
org.apache.shardingsphere
sharding-jdbc-spring-boot-starter
4.0.0-RC1
2.准备数据库,我是搞了6个库,表结构都是一样的
>>> one_master,one_slave1,one_slave2
>>> two_master,two_slave1,two_slave2
3.SQL脚本,每个库都要执行一份
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for dict
-- ----------------------------
DROP TABLE IF EXISTS `dict`;
CREATE TABLE `dict` (
`id` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
`type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for user_0
-- ----------------------------
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` (
`phone` bigint(20) NOT NULL COMMENT '主键手机号',
`user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
`pass_word` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
`auth_code` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '验证码',
`sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别0:女,1:男,2未知;',
`age` int(4) NULL DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`phone`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` (
`phone` bigint(20) NOT NULL COMMENT '主键手机号',
`user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
`pass_word` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
`auth_code` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '验证码',
`sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别0:女,1:男,2未知;',
`age` int(4) NULL DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`phone`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for user_2
-- ----------------------------
DROP TABLE IF EXISTS `user_2`;
CREATE TABLE `user_2` (
`phone` bigint(20) NOT NULL COMMENT '主键手机号',
`user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
`pass_word` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
`auth_code` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '验证码',
`sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别0:女,1:男,2未知;',
`age` int(4) NULL DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`phone`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for user_info_0
-- ----------------------------
DROP TABLE IF EXISTS `user_info_0`;
CREATE TABLE `user_info_0` (
`id` int(64) NOT NULL COMMENT '主键id',
`user_id` bigint(20) NULL DEFAULT NULL COMMENT 'user表的phone字段值',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for user_info_1
-- ----------------------------
DROP TABLE IF EXISTS `user_info_1`;
CREATE TABLE `user_info_1` (
`id` int(64) NOT NULL COMMENT '主键id',
`user_id` bigint(20) NULL DEFAULT NULL COMMENT 'user表的phone字段值',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for user_info_2
-- ----------------------------
DROP TABLE IF EXISTS `user_info_2`;
CREATE TABLE `user_info_2` (
`id` int(64) NOT NULL COMMENT '主键id',
`user_id` bigint(20) NULL DEFAULT NULL COMMENT 'user表的phone字段值',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
3.第一种:springboot的配置文件设置
spring:
shardingsphere:
datasource:
names: ds-master1,ds-master1-slave1,ds-master1-slave2,ds-master2,ds-master2-slave1,ds-master2-slave2
############################################ ###################################################
####可以像我下面这么写ds-****,不可以这么写ds_****,会报错的
ds-master1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/one_master?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: root
ds-master1-slave1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/one_slave1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: root
ds-master1-slave2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/one_slave2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: root
############################################ ###################################################
ds-master2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/two_master?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: root
ds-master2-slave1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/two_slave1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: root
ds-master2-slave2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/two_slave2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: root
sharding:
tables:
###### ######
user:
actual-data-nodes: ds$->{0..1}.user_$->{0..2}
table-strategy:
inline:
sharding-column: phone
algorithm-expression: user_$->{phone % 3}
###### ######
user_info:
actual-data-nodes: ds$->{0..1}.user_info_$->{0..2}
table-strategy:
inline:
sharding-column: user_id
algorithm-expression: user_info_$->{user_id % 3}
key-generator:
column: id
type: SNOWFLAKE
####默认数据库策略
default-database-strategy:
inline:
sharding-column: phone
algorithm-expression: ds$->{phone % 2}
####绑定表>>>user表与user_info表有关系 例如:user的phone和user_info的user_id是一样的值
binding-tables: user,user_info
####广播表>>>每个数据库都存在, 且数据都是一样的
broadcast-tables: dict
####主从规则
master-slave-rules:
ds0:
master-data-source-name: ds-master1
slave-data-source-names: ds-master1-slave1,ds-master1-slave2
ds1:
master-data-source-name: ds-master2
slave-data-source-names: ds-master2-slave1,ds-master2-slave2
####均衡方式
masterslave:
load-balance-algorithm-type: ROUND_ROBIN
main:
allow-bean-definition-overriding: true
4.第二种java代码
package com.example.common.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.example.common.db.apachesharding.ApacheShardingDatabase;
import com.example.common.db.apachesharding.ApacheShardingTable;
import com.google.common.collect.Lists;
import org.apache.shardingsphere.api.config.masterslave.MasterSlaveRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.core.constant.properties.ShardingPropertiesConstant;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;
/**
* apache的分库分表
* @author 孙灵达
*/
@Configuration
public class ApacheShardingConfig {
/**
* sharding
* @author 孙灵达
*/
@Bean
public DataSource shardingDataSource() throws SQLException, ReflectiveOperationException {
ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
shardingRuleConfiguration.getTableRuleConfigs().add(getUserRuleConfig());
shardingRuleConfiguration.getTableRuleConfigs().add(getUserInfoRuleConfig());
shardingRuleConfiguration.getBindingTableGroups().add("user, user_info");
shardingRuleConfiguration.getBroadcastTables().add("dict");
shardingRuleConfiguration.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("phone", new ApacheShardingDatabase()));
shardingRuleConfiguration.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("phone", new ApacheShardingTable()));
shardingRuleConfiguration.setMasterSlaveRuleConfigs(getMasterSlaveConfig());
Properties properties = new Properties();
properties.setProperty(ShardingPropertiesConstant.SQL_SHOW.getKey(), "true");
return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfiguration, properties);
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean() throws SQLException, ReflectiveOperationException {
DataSource dataSource = shardingDataSource();
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean;
}
@Bean
public DataSourceTransactionManager transactionManager() throws SQLException, ReflectiveOperationException {
DataSourceTransactionManager manager = new DataSourceTransactionManager();
manager.setDataSource(shardingDataSource());
return manager;
}
/**
* user_info表的分片规则
* @author 孙灵达
*/
private TableRuleConfiguration getUserInfoRuleConfig() {
TableRuleConfiguration userInfoRuleConfig = new TableRuleConfiguration("user_info", "ds${0..1}.user_info_${0..2}");
KeyGeneratorConfiguration keyGeneratorConfiguration = new KeyGeneratorConfiguration("SNOWFLAKE", "id");
userInfoRuleConfig.setKeyGeneratorConfig(keyGeneratorConfiguration);
return userInfoRuleConfig;
}
/**
* user表的分片规则
* @author 孙灵达
*/
private TableRuleConfiguration getUserRuleConfig() {
TableRuleConfiguration userRuleConfig = new TableRuleConfiguration("user", "ds${0..1}.user_${0..2}");
KeyGeneratorConfiguration keyGeneratorConfiguration = new KeyGeneratorConfiguration("SNOWFLAKE", "phone");
userRuleConfig.setKeyGeneratorConfig(keyGeneratorConfiguration);
return userRuleConfig;
}
/**
* 获取主从数据源配置
* @author 孙灵达
*/
private List getMasterSlaveConfig() {
MasterSlaveRuleConfiguration msConfig1 =
new MasterSlaveRuleConfiguration("ds0", "ds_master1", Arrays.asList("ds_master1_slave1", "ds_master1_slave2"));
MasterSlaveRuleConfiguration msConfig2 =
new MasterSlaveRuleConfiguration("ds1", "ds_master2", Arrays.asList("ds_master2_slave1", "ds_master2_slave2"));
return Lists.newArrayList(msConfig1, msConfig2);
}
/**
* 数据源配置
* @author 孙灵达
*/
private Map createDataSourceMap() throws ReflectiveOperationException {
final Map dbMap = new HashMap<>();
dbMap.put("ds_master1", getDataSource("one_master"));
dbMap.put("ds_master1_slave1", getDataSource("one_slave1"));
dbMap.put("ds_master1_slave2", getDataSource("one_slave2"));
dbMap.put("ds_master2", getDataSource("two_master"));
dbMap.put("ds_master2_slave1", getDataSource("two_slave1"));
dbMap.put("ds_master2_slave2", getDataSource("two_slave2"));
return dbMap;
}
/**
* 获取数据源
* @author 孙灵达
*/
private DataSource getDataSource(final String dbName) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDbType("com.alibaba.druid.pool.DruidDataSource");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl(String.format("jdbc:mysql://127.0.0.1:3306/%s?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT", dbName));
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
}
5.我当时这么写的时候会报错
5.是因为默认加载了shardingsphere的SpringBootConfiguration, 然后排除掉, 就可以了
6.数据库分片策略, 要注意实现类PreciseShardingAlgorithm后面的类型, 要与你分片的实体类主键类型对应(可自己定义)
package com.example.common.db.apachesharding;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
public final class ApacheShardingDatabase implements PreciseShardingAlgorithm {
@Override
public String doSharding(final Collection databaseNames, final PreciseShardingValue shardingValue) {
for (String database : databaseNames) {
if (database.endsWith((shardingValue.getValue() % 2) + "")) {
System.out.println("数据库:" + database);
return database;
}
}
throw new UnsupportedOperationException();
}
}
7.表的分片策略, 和分库策略一样, 类型要对应上
package com.example.common.db.apachesharding;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
public final class ApacheShardingTable implements PreciseShardingAlgorithm {
@Override
public String doSharding(final Collection tableNames, final PreciseShardingValue shardingValue) {
for (String table : tableNames) {
if (table.endsWith(shardingValue.getValue() % 3 + "")) {
System.out.println("表:" + table);
return table;
}
}
throw new UnsupportedOperationException();
}
}
8.结果
>>>插入数据会根据分片的策略进行插入;
>>>selelct * from user也会查询出所有的数据:
>>>select * from user where phone = xx这样就不会查询到对应的库和表, 目前还没有解决, 如果有办法希望您留言解答
9.相关资料链接:
shardingsphere资料:
http://shardingsphere.apache.org/document/current/cn/quick-start/
https://blog.csdn.net/caohao1210/article/details/85108118
mysql主从复制:
https://blog.csdn.net/li_lening/article/details/81878163