一、准备工作

1、准备三个数据库:db0、db1、db2

2、每个数据库新建两个订单表:t_order_0、t_order_1

DROP TABLE IF EXISTS `t_order_x`;
CREATE TABLE `t_order_x` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL,
`order_id` bigint NOT NULL,
`order_no` varchar(30) NOT NULL,
`isactive` tinyint NOT NULL DEFAULT '',
`inserttime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updatetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

二、分库分表配置

数据源的配置可以使用任何链接池,本例用druid为例。

1、引言依赖包:

引用最新的maven包

<sharding-jdbc.version>2.0.1</sharding-jdbc.version>

<dependency>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>

2、配置DataSource:

    @Bean(name = "shardingDataSource", destroyMethod = "close")
@Qualifier("shardingDataSource")
public DataSource getShardingDataSource() {
// 配置真实数据源
Map<String, DataSource> dataSourceMap = new HashMap<>(3); // 配置第一个数据源
DruidDataSource dataSource1 = createDefaultDruidDataSource();
dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
dataSource1.setUrl("jdbc:mysql://localhost:3306/db0");
dataSource1.setUsername("root");
dataSource1.setPassword("root");
dataSourceMap.put("db0", dataSource1); // 配置第二个数据源
DruidDataSource dataSource2 = createDefaultDruidDataSource();
dataSource2.setDriverClassName("com.mysql.jdbc.Driver");
dataSource2.setUrl("jdbc:mysql://localhost:3306/db1");
dataSource2.setUsername("root");
dataSource2.setPassword("root");
dataSource2.setName("db1-0001");
dataSourceMap.put("db1", dataSource2); // 配置第三个数据源
DruidDataSource dataSource3 = createDefaultDruidDataSource();
dataSource3.setDriverClassName("com.mysql.jdbc.Driver");
dataSource3.setUrl("jdbc:mysql://localhost:3306/db2");
dataSource3.setUsername("root");
dataSource3.setPassword("root");
dataSourceMap.put("db2", dataSource3); // 配置Order表规则
TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration();
orderTableRuleConfig.setLogicTable("t_order");
orderTableRuleConfig.setActualDataNodes("db${0..2}.t_order_${0..1}");
//orderTableRuleConfig.setActualDataNodes("db0.t_order_0,db0.t_order_1,db1.t_order_0,db1.t_order_1,db2.t_order_0,db2.t_order_1"); // 配置分库策略(Groovy表达式配置db规则)
orderTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "db${user_id % 3}")); // 配置分表策略(Groovy表达式配置表路由规则)
orderTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order_${order_id % 2}")); // 配置分片规则
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig); // 配置order_items表规则... // 获取数据源对象
DataSource dataSource = null;
try {
dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new ConcurrentHashMap(), new Properties());
} catch (SQLException e) {
e.printStackTrace();
}
return dataSource;
}

可以使用Druid监控db。

三、示例验证

1、新增数据

@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderMapper orderMapper; @RequestMapping("/add")
public void addOrder() {
OrderEntity entity10 = new OrderEntity();
entity10.setOrderId(10000L);
entity10.setOrderNo("No1000000");
entity10.setUserId(102333001L);
orderMapper.insertSelective(entity10);
OrderEntity entity11 = new OrderEntity();
entity11.setOrderId(10001L);
entity11.setOrderNo("No1000000");
entity11.setUserId(102333000L);
orderMapper.insertSelective(entity11);
}
}

依据配置的分片规则

  • DB路由规则:user_id % 3:

     102333001 % 3 = 1

102333000 % 3 = 0

  • 表路由规则:order_id % 2:

10000 % 2 = 0

10001 % 2 = 1

userid=102333001,orderId=10000的数据落地到db1.t_order_0
userid=102333000,orderId=10001的数据落地到db0.t_order_1

2、未指定分片规则字段的查询

    /**广播遍历所有的库和表*/
@RequestMapping("get")
public void getOrder() {
List<Integer> ids = new ArrayList<>();
ids.add(4);
List<OrderEntity> orderEntities = orderMapper.selectByPrimaryIds(ids); log.info(JSON.toJSONString(orderEntities));
}

由druid监控sql得知,查询被广播到db0、db1、db2的各个表里,如下监控所示:

3、不能执行批量插入操作

不支持对不同分片规则的字段值进行批量插入操作,类似sql:insert into t_order values(x,x,x,x),(x,x,x,x),(x,x,x,x)

4、谨慎修改分片规则字段

如果修改了分片规则的字段,比如本例的user_id或order_id,因为路由规则会造成数据存在,却查不到数据的情况。

    @RequestMapping("/upd")
public void update() {
OrderEntity orderWhere = new OrderEntity();
orderWhere.setOrderId(10001L);
orderWhere.setUserId(102333001L);
orderWhere.setId(4L); OrderEntity orderSet = new OrderEntity();
orderSet.setOrderId(10002L);
orderSet.setOrderNo("修改订单号"); orderMapper.updateByPredicate(orderSet, orderWhere); /**查不到,orderId更改会引起路由查询失败*/
OrderEntity predicate = new OrderEntity();
predicate.setOrderId(10002L);
OrderEntity entity = orderMapper.selectSingleByPredicate(predicate);
log.info("after update orderEntity:"+JSON.toJSONString(entity));
}

四、sharding建表

目前配置并验证了3个库,每库2个order表的场景:

如果分库分表数量比较多,仅仅创建表就是一件很繁琐的事情。sharding查询数据不指定分片规则字段时,会自动路由到各个库的各个表里查询,不知道大家有没有想到:如果配置要创建表的路由规则,用sharding来执行一条创建sql的语句,会不会就自动路由到各个库去执行了,也就代替人工去各个库建表了呢?下面来验证一下这个想法,以创建t_order_items表为例:

1、配置t_order_items的规则

在上面配置t_order规则下面补充t_order_items的规则配置:

        // 省略配置order_item表规则...
TableRuleConfiguration orderItemTableRuleConfig = new TableRuleConfiguration();
orderItemTableRuleConfig.setLogicTable("t_order_items");
orderItemTableRuleConfig.setActualDataNodes("db${0..2}.t_order_items_${0..1}");// 配置分库策略
orderItemTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "db${order_id % 3}")); // 配置分表策略
orderItemTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order_items_${order_id % 2}")); shardingRuleConfig.getTableRuleConfigs().add(orderItemTableRuleConfig);

2、t_order_items建表sql语句

    <update id="createTItemsIfNotExistsTable">
CREATE TABLE IF NOT EXISTS `t_order_items` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_id` bigint NOT NULL,
`unique_no` varchar(32) NOT NULL,
`quantity` int NOT NULL DEFAULT '1',
`is_active` tinyint NOT NULL DEFAULT 1,
`inserttime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updatetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</update>

3、OrderItemsMapper方法

Integer createTItemsIfNotExistsTable();

4、执行方法

orderItemsMapper.createTItemsIfNotExistsTable();

查看db0、db1、db2:

验证了我们上面的想法,建表成功了。

附录

如果没有配置t_order_items规则,执行建表sql会报错:

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: io.shardingjdbc.core.exception.ShardingJdbcException: Cannot find table rule and default data source with logic table: 't_order_items'
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: CREATE TABLE IF NOT EXISTS `t_order_items` ( `id` bigint NOT NULL AUTO_INCREMENT, `order_id` bigint NOT NULL, `unique_no` varchar(32) NOT NULL, `quantity` int NOT NULL DEFAULT '1', `is_active` tinyint NOT NULL DEFAULT 1, `inserttime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updatetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
### Cause: io.shardingjdbc.core.exception.ShardingJdbcException: Cannot find table rule and default data source with logic table: 't_order_items'

【分库分表】sharding-jdbc实践—分库分表入门的更多相关文章

  1. sharding jdbc(sphere) 3.1.0 spring boot配置

    sharding jdbc 2.x系列详解参见https://www.cnblogs.com/zhjh256/p/9221634.html. 最近将sharding jdbc的配置从xml切换到了sp ...

  2. Sharding JDBC整合SpringBoot 2.x 和 MyBatis Plus 进行分库分表

    Sharding JDBC整合SpringBoot 2.x 和 MyBatis Plus 进行分库分表 交易所流水表的单表数据量已经过亿,选用Sharding-JDBC进行分库分表.MyBatis-P ...

  3. 转数据库分库分表(sharding)系列(二) 全局主键生成策略

    本文将主要介绍一些常见的全局主键生成策略,然后重点介绍flickr使用的一种非常优秀的全局主键生成方案.关于分库分表(sharding)的拆分策略和实施细则,请参考该系列的前一篇文章:数据库分库分表( ...

  4. 数据库分库分表(sharding)系列【转】

    原文地址:http://www.uml.org.cn/sjjm/201211212.asp数据库分库分表(sharding)系列 目录; (一) 拆分实施策略和示例演示 (二) 全局主键生成策略 (三 ...

  5. 数据库分库分表(sharding)系列(二) 全局主键生成策略

    本文将主要介绍一些常见的全局主键生成策略,然后重点介绍flickr使用的一种非常优秀的全局主键生成方案.关于分库分表(sharding)的拆分策略和实施细则,请参考该系列的前一篇文章:数据库分库分表( ...

  6. 数据库分库分表(sharding)系列

    数据库分库分表(sharding)系列     目录; (一) 拆分实施策略和示例演示 (二) 全局主键生成策略 (三) 关于使用框架还是自主开发以及sharding实现层面的考量 (四) 多数据源的 ...

  7. Sharding Sphere的分库分表

    什么是 ShardingSphere? 1.一套开源的分布式数据库中间件解决方案 2.有三个产品:Sharding-JDBC 和 Sharding-Proxy 3.定位为关系型数据库中间件,合理在分布 ...

  8. 数据库分库分表(sharding)系列(一) 拆分规则

    第一部分:实施策略 数据库分库分表(sharding)实施策略图解 1. 垂直切分垂直切分的依据原则是:将业务紧密,表间关联密切的表划分在一起,例如同一模块的表.结合已经准备好的数据库ER图或领域模型 ...

  9. 转数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示

    本文原文连接: http://blog.csdn.net/bluishglc/article/details/7696085 ,转载请注明出处!本文着重介绍sharding切分策略,如果你对数据库sh ...

随机推荐

  1. 模拟window桌面实现

    正在开发中的游戏有个全屏功能--可以在window桌面背景上运行,就像一些视频播放器在桌面背景上播放一样的,花了个上午整了个Demo放出来留个纪念. 实现功能:显示图标,双击图标执行相应的程序,右击图 ...

  2. 160427、CSS3实战笔记--多列布局

    通过阅读和学习书籍<CSS3实战>总结 <CSS3实战>/成林著.—北京机械工业出版社2011.5   多列布局适合纯文字版式设计,如报纸内和杂志类网页布局,不适合做网页结构布 ...

  3. 不想分页怎么办??-->页面数据的滚动加载

    在前几天的一次前台数据展示的时候 为了更好的用户的体验 就想着做一个数据的滚动加载功能 于是简单的查询了网上的实现方式 基本都是在页面加载的时候绑定scroll事件 然后判断页面触底的时候 进行aja ...

  4. poj3233—Matrix Power Series

    题目链接:http://poj.org/problem?id=3233 题目意思:给一个矩阵n*n的矩阵A和一个k,求一个式子 S = A + A2 + A3 + … + Ak. 这个需要用到等比数列 ...

  5. time-based DB

    这类时间序列数据库最多,使用也最广泛.一般人们谈论时间序列数据库的时候指代的就是这一类存储.按照底层技术不同可以划分为三类. 直接基于文件的简单存储:RRD Tool,Graphite Whisper ...

  6. F5刷新与在地址栏按回车的区别

    “F5刷新”,它是在你现有页面的基础上,检查网页是否有更新的内容.在检查时,会保留之前的一些变量的值: “转到”和在地址栏回车,则相当于你重新输入网页的URL访问,这种情况下,浏览器会尽量使用已经存在 ...

  7. 前端开发 - JQuery - 中

    十四.jquery属性操作 attr prop <!DOCTYPE html> <html lang="en"> <head> <meta ...

  8. Windows10安装MySQL5.6.24

    1.解压安装包到指定目录如:E:\Java\mysql-5.6-24-win32 2.在E:\Java\mysql-5.6-24-win32目录下新建my.ini文件,内容如下 [mysqld] ba ...

  9. 【react表格组件】react-virtualized虚拟列表

    https://css-tricks.com/rendering-lists-using-react-virtualized/

  10. MFC工具栏设计

    工具栏中包含了一组用于执行命令的按钮,每个按钮都用一个图标来表示.当单击某个按钮时,会产生一个相应的消息,对这个消息的处理就是按钮的功能实现.将菜单中常用的功能放置在工具栏中,这样可以方便用户操作,省 ...