本文共 9728 字,大约阅读时间需要 32 分钟。
接上一张分库分表分析。项目代码地址:
1.引入jar包org.springframework.boot spring-boot-starter-parent 2.1.5.RELEASE org.springframework.boot spring-boot-starter-web mysql mysql-connector-java org.mybatis.spring.boot mybatis-spring-boot-starter 1.2.0 com.alibaba druid 1.1.9 io.shardingsphere sharding-jdbc-spring-boot-starter 3.1.0
2.新建表t_user_1和t_user_2,表结构完全一样
3.新建工程sharding-jdbc,结构 mapper接口public interface TUserMapper { int insert(TUser user);}
mapper接口对应的xml
INSERT INTO t_user (user_name,age,remark) VALUES (#{userName}, #{age}, #{remark})
service接口
public interface TUserService { boolean insert(TUser user);}
service接口实现类
@Servicepublic class TUserServiceImpl implements TUserService{ @Autowired private TUserMapper tUserMapper; @Override public boolean insert(TUser user) { return this.tUserMapper.insert(user) == 1; }}
TUser实体类
public class TUser implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String userName; private Integer age; private String remark; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; }}
Controller类
@RestControllerpublic class TUserController { @Autowired private TUserService tUserService; @GetMapping("/add") public String add(){ TUser user = new TUser(); user.setUserName("张三"); user.setAge(20); user.setRemark("..."); boolean result = this.tUserService.insert(user); if(result){ return "success"; } return "fail"; }}
application.properties配置,本文采用的是sharding-jdbc-spring-boot-starter的3.1.0版本的,所以配置文件需以sharding.jdbc.开头
水平分表不分库配置#spring.main.allow-bean-definition-overriding=true#配置数据源的详细信息,多个逗号分开sharding.jdbc.datasource.names=m1# 数据库连接池sharding.jdbc.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource#数据库驱动类名sharding.jdbc.datasource.m1.driver-class-name=com.mysql.jdbc.Driver# 数据库 URL 连接sharding.jdbc.datasource.m1.url=jdbc:mysql://localhost:3306/sharding-jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC# 数据库用户名sharding.jdbc.datasource.m1.username=root# 数据库密码sharding.jdbc.datasource.m1.password=123456# 指定t_user表的分布情况,配置在哪个数据库,表名称是什么 m1.t_user_1 m1.t_user_2sharding.jdbc.config.sharding.tables.t_user.actual-data-nodes=m1.t_user_$->{1..2}#指定t_user表中主键的生成策略 SNOWFLAKE:雪花算法,随机生成主键Idsharding.jdbc.config.sharding.tables.t_user.key-generator-column-name=idsharding.jdbc.config.sharding.tables.t_user.key-generator-type=SNOWFLAKE# 指定分片的策略 约定id值 : 偶数--》t_user_1 奇数-->t_user_2sharding.jdbc.config.sharding.tables.t_user.table-strategy.inline.sharding-column=idsharding.jdbc.config.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user_$->{id%2 +1}#打开sql的输出日志sharding.jdbc.config.sharding.props.sql.show=true#实体类扫描配置,这样在mapper的xml中可以直接使用实体类名,不用写包路径mybatis.type-aliases-package=com.xqc.mode#驼峰转换mybatis.configuration.mapUnderscoreToCamelCase=true#处理日期spring.jackson.date-format=yyyy-MM-dd HH:mmspring.jackson.time-zone=GMT+8#xml文件扫描mybatis.mapperLocations=classpath:mapper/*.xml
启动类配置
@SpringBootApplication@MapperScan("com.xqc.dao")//mapper接口扫描public class App { public static void main( String[] args ){ SpringApplication.run(App.class, args); } }
4.浏览器多次访问查看数据库数据
主键ID尾数奇数的存在t_user_2表中 主键ID尾数偶数的存在t_user_1表中 上面数据存储采用的是自带的inline算法,我们也可以根据自己的需求,自定义分片算法# 自定义分表算法sharding.jdbc.config.sharding.tables.t_user.table-strategy.standard.sharding-column=idsharding.jdbc.config.sharding.tables.t_user.table-strategy.standard.precise-algorithm-class-name=com.xqc.algorithm.MyPreciseShardingAlgorithm
实现接口PreciseShardingAlgorithm
/*** @dateTime 创建时间:2020年8月19日 上午10:19:06* @version V1.0.0* 类说明 自定义分表算法,尾数0-5存表t_user_1,6-9存表t_user_2*/public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm{ private static final List PARAM_LIST = Arrays.asList("0","1","2","3","4","5"); @Override public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) { //availableTargetNames拆分出来的物理表【t_user_1,t_user_2】,shardingValue分片字段的值 for (String availableTargetName : availableTargetNames) { String value = "2" ; //尾数0-5存表t_user_1,6-9存表t_user_2 String colValue = shardingValue.getValue().toString(); String subLast = shardingValue.getValue().toString().substring(colValue.length()-1, colValue.length()); if(PARAM_LIST.contains(subLast)){ value = "1"; } if(availableTargetName.endsWith(value)){ return availableTargetName; } } throw new IllegalArgumentException(); }}
再看数据库数据
分片算法介绍
通过分片算法将数据分片,支持通过=、BETWEEN和IN分片。分片算法需要应用方开发者自行实现,可实现的灵活度非常高。 精确分片算法 对应PreciseShardingAlgorithm,用于处理使用单一键作为分片键的=与IN进行分片的场景。需要配合StandardShardingStrategy使用。 范围分片算法 对应RangeShardingAlgorithm,用于处理使用单一键作为分片键的BETWEEN AND进行分片的场景。需要配合StandardShardingStrategy使用。 复合分片算法 对应ComplexKeysShardingAlgorithm,用于处理使用多键作为分片键进行分片的场景,包含多个分片键的逻辑较复杂,需要应用开发者自行处理其中的复杂度。需要配合ComplexShardingStrategy使用。 Hint分片算法 对应HintShardingAlgorithm,用于处理使用Hint行分片的场景。需要配合HintShardingStrategy使用。水平分库分表配置:不同的数据库,相同的表结构,每个库都有多份
#分库不分表的情况#spring.main.allow-bean-definition-overriding=true#配置数据源的详细信息,多个逗号分开sharding.jdbc.datasource.names=m1,m2#数据库1# 数据库连接池sharding.jdbc.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource#数据库驱动类名sharding.jdbc.datasource.m1.driver-class-name=com.mysql.jdbc.Driver# 数据库 URL 连接sharding.jdbc.datasource.m1.url=jdbc:mysql://localhost:3306/sharding-jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC# 数据库用户名sharding.jdbc.datasource.m1.username=root# 数据库密码sharding.jdbc.datasource.m1.password=123456#数据库2# 数据库连接池sharding.jdbc.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource#数据库驱动类名sharding.jdbc.datasource.m2.driver-class-name=com.mysql.jdbc.Driver# 数据库 URL 连接sharding.jdbc.datasource.m2.url=jdbc:mysql://localhost:3306/sharding-jdbc_02?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC# 数据库用户名sharding.jdbc.datasource.m2.username=root# 数据库密码sharding.jdbc.datasource.m2.password=123456# 指定分库的策略 约定id值 : 偶数--》m1 奇数-->m2sharding.jdbc.config.sharding.tables.t_user.database-strategy.inline.sharding-column=idsharding.jdbc.config.sharding.tables.t_user.database-strategy.inline.algorithm-expression=m$->{id%2 +1}# 指定t_user表的分布情况,配置在哪个数据库,表名称是什么 m1.t_user_1 m1.t_user_2sharding.jdbc.config.sharding.tables.t_user.actual-data-nodes=m$->{1..2}.t_user_$->{1..2}#指定t_user表中主键的生成策略 SNOWFLAKE:雪花算法,随机生成主键Idsharding.jdbc.config.sharding.tables.t_user.key-generator-column-name=idsharding.jdbc.config.sharding.tables.t_user.key-generator-type=SNOWFLAKE#指定表的分表算法sharding.jdbc.config.sharding.tables.t_user.table-strategy.inline.sharding-column=pidsharding.jdbc.config.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user_$->{pid%2 +1}#打开sql的输出日志sharding.jdbc.config.sharding.props.sql.show=true#实体类扫描配置,这样在mapper的xml中可以直接使用实体类名,不用写包路径mybatis.type-aliases-package=com.xqc.mode#驼峰转换mybatis.configuration.mapUnderscoreToCamelCase=true#处理日期spring.jackson.date-format=yyyy-MM-dd HH:mmspring.jackson.time-zone=GMT+8#xml文件扫描mybatis.mapperLocations=classpath:mapper/*.xml
水平分库不分表配置:相同的表结构,放在多个数据库中,根据分库算法存放数据,访问地址
#分库不分表的情况#spring.main.allow-bean-definition-overriding=true#配置数据源的详细信息,多个逗号分开sharding.jdbc.datasource.names=m1,m2#数据库1# 数据库连接池sharding.jdbc.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource#数据库驱动类名sharding.jdbc.datasource.m1.driver-class-name=com.mysql.jdbc.Driver# 数据库 URL 连接sharding.jdbc.datasource.m1.url=jdbc:mysql://localhost:3306/sharding-jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC# 数据库用户名sharding.jdbc.datasource.m1.username=root# 数据库密码sharding.jdbc.datasource.m1.password=123456#数据库2# 数据库连接池sharding.jdbc.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource#数据库驱动类名sharding.jdbc.datasource.m2.driver-class-name=com.mysql.jdbc.Driver# 数据库 URL 连接sharding.jdbc.datasource.m2.url=jdbc:mysql://localhost:3306/sharding-jdbc_02?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC# 数据库用户名sharding.jdbc.datasource.m2.username=root# 数据库密码sharding.jdbc.datasource.m2.password=123456# 指定t_user表的分布情况,配置在哪个数据库,表名称是什么 m1.t_user_1 m1.t_user_2#sharding.jdbc.config.sharding.tables.t_role.actual-data-nodes=m1.t_user_$->{1..2}#指定t_user表中主键的生成策略 SNOWFLAKE:雪花算法,随机生成主键Idsharding.jdbc.config.sharding.tables.t_role.key-generator-column-name=idsharding.jdbc.config.sharding.tables.t_role.key-generator-type=SNOWFLAKE# 指定分片的策略 约定id值 : 偶数--》m1 奇数-->m2# 自定义分库算法sharding.jdbc.config.sharding.tables.t_role.database-strategy.inline.sharding-column=idsharding.jdbc.config.sharding.tables.t_role.database-strategy.inline.algorithm-expression=m$->{id%2 +1}#打开sql的输出日志sharding.jdbc.config.sharding.props.sql.show=true#实体类扫描配置,这样在mapper的xml中可以直接使用实体类名,不用写包路径mybatis.type-aliases-package=com.xqc.mode#驼峰转换mybatis.configuration.mapUnderscoreToCamelCase=true#处理日期spring.jackson.date-format=yyyy-MM-dd HH:mmspring.jackson.time-zone=GMT+8#xml文件扫描mybatis.mapperLocations=classpath:mapper/*.xmlsharding-jdbc执行流程 SQL路由:根据解析上下文匹配用户配置的分片策略,并生成最终的路由路径 SQL改写:将SQL改写为在真实数据库中可以正确执行的语句。
转载地址:http://jiwmf.baihongyu.com/