热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

分库分表ShardingJDBC(详解1/6)

狂创客圈经典图书:《NettyZookeeperRedis高并发实战》面试必备+面试必备+面试必备【博客园总入口】疯狂创客圈经典图书:《SpringCloud、Nginx高并发核心




  • 狂创客圈 经典图书 : 《Netty Zookeeper Redis 高并发实战》 面试必备 + 面试必备 + 面试必备 【博客园总入口 】

  • 疯狂创客圈 经典图书 : 《SpringCloud、Nginx高并发核心编程》 大厂必备 + 大厂必备 + 大厂必备 【博客园总入口 】

  • 入大厂+涨工资必备: 高并发【 亿级流量IM实战】 实战系列 【 SpringCloud Nginx秒杀】 实战系列 【博客园总入口 】




目录:分库分表 Sharding-JDBC从入门到精通
主题链接地址
准备1: 在window安装虚拟机集群分布式 虚拟机 linux 环境制作 GO
准备2:在虚拟机的各个节点有 mysqlcentos mysql 笔记(内含vagrant mysql 镜像)GO
分库分表 -Sharding-JDBC- 从入门到精通 1Sharding-JDBC 分库、分表(入门实战) GO
分库分表 -Sharding-JDBC- 从入门到精通 2Sharding-JDBC 基础知识 GO
分库分表 Sharding-JDBC 从入门到精通之 3自定义主键、分布式雪花主键,原理与实战 GO
分库分表 -Sharding-JDBC- 从入门到精通 4MYSQL集群主从复制,原理与实战 GO
分库分表 Sharding-JDBC 从入门到精通之 5读写分离 实战 GO
分库分表 Sharding-JDBC 从入门到精通之 6Sharding-JDBC执行原理 GO
分库分表 Sharding-JDBC 从入门到精通之源码git仓库地址GO

1.有关Sharding-JDBC

有关Sharding-JDBC介绍这里就不在多说,之前Sharding-JDBC是当当网自研的关系型数据库的水平扩展框架,现在已经捐献给Apache,其原理请参见后面的博客。

shardingsphere文档地址是:https://shardingsphere.apache.org/document/current/cn/overview/。


2 Sharding-JDBC 实战的场景

在深入了解之前,先实战一把,增加印象, 激发兴趣。

一般情况下,大家都会使用水平切分库和表:将一张表水平切分成多张表,还可以放到多个库中。这就涉及到数据分片的规则,比较常见的有:Hash取模分表、数值Range分表、一致性Hash算法分表。


1、Hash取模分表

概念 一般采用Hash取模的切分方式,例如:假设按goods_id分4张表。(goods_id%4 取整确定表)

img


优点


  • 数据分片相对比较均匀,不容易出现热点和并发访问的瓶颈。

缺点


  • 后期分片集群扩容时,需要迁移旧的数据很难。

  • 容易面临跨分片查询的复杂问题。比如上例中,如果频繁用到的查询条件中不带goods_id时,将会导致无法定位数据库,从而需要同时向4个库发起查询,
    再在内存中合并数据,取最小集返回给应用,分库反而成为拖累。


2、数值Range分表

概念 按照时间区间或ID区间来切分。例如:将goods_id为11000的记录分到第一个表,10012000的分到第二个表,以此类推。

img


优点


  • 单表大小可控
  • 天然便于水平扩展,后期如果想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移
  • 使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。

缺点


  • 热点数据成为性能瓶颈。
    例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询

3、一致性Hash算法

一致性Hash算法能很好的解决因为Hash取模而产生的分片集群扩容时,需要迁移旧的数据的难题。至于具体原理这里就不详细说,

可以参考一篇博客:一致性哈希算法(分库分表,负载均衡等)


4、实战:简单的Hash取模分表

假设一个订单表的user_id和order_id 分布较为均匀,按照1000W的数据规模,可以使用如下的分库、分表结构来保存:

db0
├── t_order0
└── t_order1
db1
├── t_order0
└── t_order1

简单的进行分库分表: 按照user_id %2 的规则进行分库,按照 order_id %2 的规则进行分表



3 库表的结构设计:

3.1 逻辑订单表

逻辑订单表的结构如下:


3.2 节点1 (cdh1)上的订单库

DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` bigInt NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` bigInt NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));

3.3 节点2 (cdh2)上的订单库

DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` bigInt NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` bigInt NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));

两个db上,都有t_order_0,和t_order_1两个表


4 Sharding-JDBC 分库分表配置
  • 分库

本文分库样例比较简单,根据数据库表中字段user_id%2进行判断,如果user_id%2==0则使用ds0,否则使用ds1。


  • 分表

分样例比较简单,根据数据库表中字段order_id%2进行判断,如果order_id%2==0则使用t_order_0,否则使用t_order_1。

对 t_order 表进行的如下图所示的数据表水平 分库和分表,具体如下图所示:


5.4 服务层

在这里插入图片描述

更多详细内容请参见源码工程。


5.4 Controller

接下来创建一个Controller进行测试,保存方法使用了插入数据和查看数据,根据我们的规则,会每个库插入数据,同时我这里还创建了一个查询方法,查询全部订单。

package com.crazymaker.springcloud.sharding.jdbc.demo.controller;
@RestController
@RequestMapping("/api/sharding/")
@Api(tags = "sharding jdbc 演示")
public class ShardingJdbcController
{
@Resource
JpaEntityService jpaEntityService;
@PostMapping("/order/add/v1")
@ApiOperation(value = "插入订单")
public RestOut orderAdd(@RequestBody Order dto)
{
jpaEntityService.addOrder(dto);
return RestOut.success(dto);
}
@PostMapping("/order/list/v1")
@ApiOperation(value = "查询订单")
public RestOut> listAll()
{
List list = jpaEntityService.selectAll();
return RestOut.success(list);
}
}

6 执行测试

6.1 打开swagger

启动应用。

然后,在浏览器或HTTP请求工具访问http://localhost:7700/sharding-jdbc-provider/swagger-ui.html,如图所示

在这里插入图片描述


6.2 加入两条数据

在这里插入图片描述

使用插入订单的接口,可以插入订单, 注意 userid %2 ==0 进入 db1, 注意 userid %2 ==1进入 db2, 具体在哪个表呢?

因为 orderid是通过雪花算法生成的,如果orderid%2==0 ,则进入t_order_0,否则使用t_order_1。

插入之后,可以通过数据库,看结果。具体如下图:

在这里插入图片描述


6.3 查看数据

在这里插入图片描述

使用程序的查询全部的方法,shardingjdbc ,会查出所有的订单。


7 总结

使用shardingjdbc ,除了数据源的配置有些特殊的规则外, 持久层程序和普通的 JPA代码,区别并不大。


当然,如果要实现特殊的分库分表逻辑,还是需要动代码的,请看后续分解。



回到◀疯狂创客圈▶

疯狂创客圈 - Java高并发研习社群,为大家开启大厂之门



推荐阅读
author-avatar
情之瞬
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有