「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战」
Sharding-JDBC入门使用
搭建基础环境
- 需求说明
创建数据库lg_order,模拟将订单表进行水平拆分,创建两张表pay_order_1与pay_order_2,这两张表是订单表拆分后的表,我们通过Sharding-Jdbc向订单表插入数据,按照一定的分片规则,主键为偶数的落入pay_order_1表 ,为奇数的落入pay_order_2表,再通过Sharding-Jdbc进行查询
- 创建数据库
1 | mysql复制代码CREATE DATABASE lg_order CHARACTER SET 'utf8'; |
- 创建SpringBoot项目引入maven依赖
sharding-jdbc以jar包形式提供服务,所以要先引入maven依赖。
1 | xml复制代码<dependency> |
分片规则配置(水平分表)
使用sharding-jdbc对数据库中水平拆分的表进行操作,通过sharding-jdbc对分库分表的规则进行配置,配置内容包括:数据源、主键生成策略、分片策略等。
application.properties
- 基础配置
1 | properties复制代码spring.application.name = sharding-jdbc-simple |
- 数据源
1 | properties复制代码# 定义数据源 |
- 配置数据节点
1 | properties复制代码#配置数据节点,指定节点的信息 |
表达式db1.pay_order_$->{1..2}
$会被大括号中的{1..2}所替换
会有两种选择:db1.pay_order_1和db1.pay_order_2
- 配置主键生成策略
1 | properties复制代码#指定pay_order表 (逻辑表)的主键生成策略为 SNOWFLAKE |
使用shardingJDBC提供的主键生成策略,全局主键
为避免主键重复,生成主键采用SNOWFLAKE分布式ID生成算法
- 配置分片算法
1 | properties复制代码#指定pay_order表的分片策略,分片策略包括分片键和分片算法 |
分表策略表达式:pay_order_$-> {order_id % 2 + 1}
{order_id % 2 + 1} 结果是偶数操作pay_order_1表
{order_id % 2 + 1} 结果是奇数操作pay_order_2表
- 打开SQL日志
1 | properties复制代码# 打开sql输出日志 |
- 步骤总结
- 定义数据源
- 指定pay_order表的数据分布情况,分布在pay_order_1和pay_order_2
- 指定pay_order表的主键生成策略为SNOWFLAKE,是一种分布式自增算法,保证id全局唯一
- 定义pay_order分片策略,order_id为偶数的数据下沉到pay_order_1,为奇数下沉到在pay_order_2
编写程序
- 新增订单
1 | java复制代码@Mapper |
- 测试
1 | java复制代码@RunWith(SpringRunner.class) |
- 根据Id查询订单
1 | java复制代码/** |
- 测试
1 | java复制代码@Test |
ShardingJDBC执行流程
当ShardingJDBC接收到发送的SQL之后,会执行下面的步骤,最终返回执行结果
- SQL解析:编写SQL查询的是逻辑表,执行时ShardingJDBC要解析SQL,解析的目的是为了找到需要改写的位置。
- SQL路由:SQL的路由是指将对逻辑表的操作,映射到对应的数据节点的过程。ShardingJDBC会获取分片键判断是否正确,正确就执行分片策略(算法)来找到真实的表。
- SQL改写:程序员面向的是逻辑表编写SQL,并不能直接在真实的数据库中执行,SQL改写用于将逻辑SQL改为在真实的数据库中可以正确执行的SQL。
- SQL执行:通过配置规则pay_order_$->{order_id % 2 + 1},可以知道当order_id为偶数时,应该向 pay_order_1表中插入数据,为奇数时向pay_order_2表插入数据。
- 将所有真正执行sql的结果进行汇总合并,然后返回。
Sharding-JDBC分库分表
水平分表
把一张表的数据按照一定规则,分配到同一个数据库的多张表中,每个表只有这个表的部分数据。在Sharding-JDBC入门使用中,我们已经完成了水平分表的操作。
水平分库
水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。接下来看一下如何使用Sharding-JDBC实现水平分库
将原来的lg_order数据库,拆分为lg_order_1和lg_order_2
- 分片规则配置
现在是两个数据库,所以要配置两份数据源信息。
1 | properties复制代码# 定义多个数据源 |
通过配置对数据库的分片策略,来指定数据库进行操作
1 | properties复制代码# 分库策略,以user_id为分片键,分片策略为user_id % 2 + 1,user_id为偶数操作db1数据源,否则操作db2。 |
- 分库分表的策略
- 分库策略,目的是将一个逻辑表,映射到多个数据源
1 | properties复制代码# 分库找的是数据库 db$->{user_id % 2 + 1} |
1 | diff复制代码- 分表策略,如何将一个逻辑表,映射为多个实际表 |
1 | properties复制代码#分表 找的是具体的表 pay_order_$->{order_id % 2 + 1} |
- Sharding-JDBC支持以下几种分片策略:
- standard:标准分片策略
- complex:符合分片策略
- inline:行表达式分片策略,,使用Groovy的表达式.
- hint:Hint分片策略,对应HintShardingStrategy。
- none:不分片策略,对应NoneShardingStrategy。不分片的策略。
具体信息请查阅官方文档:shardingsphere.apache.org
- 插入测试
1 | java复制代码@Test |
首先会根据分库策略找到对应的数据库db$->{user_id % 2 + 1}
然后再根据分表策略找到要插入数据的表pay_order_$->{order_id % 2 + 1}
- 查询测试
1 | java复制代码@Test |
通过日志发现,sharding-jdbc将sql路由到了db1
原因在配置上有问题,数据库只指定了db1
- 修改数据节点配置
1 | properties复制代码#数据节点: db1.pay_order_1 , db1.pay_order_2, db2.pay_order_1,db2.pay_order_2 |
垂直分库
垂直分库是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用。
在使用微服务架构时,业务切割得足够独立,数据也会按照业务切分,保证业务数据隔离,大大提升了数据库的吞吐能力。
- 创建数据库
1 | mysql复制代码CREATE DATABASE lg_user CHARACTER SET 'utf8'; |
- 在lg_user数据库中users创建表
1 | mysql复制代码DROP TABLE IF EXISTS users; |
- 规则配置
- 配置数据源信息
1 | properties复制代码spring.shardingsphere.datasource.names = db1,db2,db3 |
- 配置数据节点
1 | properties复制代码spring.shardingsphere.sharding.tables.users.actual-data-nodes = db$->{3}.users |
1 | properties复制代码spring.shardingsphere.sharding.tables.users.table-strategy.inline.sharding-column = id |
- 测试插入与查询
- UserDao
1 | java复制代码@Mapper |
- UserDaoTest
1 | java复制代码@RunWith(SpringRunner.class) |
Sharding-JDBC 操作公共表
什么是公共表
公共表属于系统中数据量较小,变动少,而且属于高频联合查询的依赖表。参数表、数据字典表等属于此类型。
可以将这类表在每个数据库都保存一份,所有更新操作都同时发送到所有分库执行。接下来看一下如何使用Sharding-JDBC实现公共表的数据维护。
公共表配置与测试
- 创建数据库
分别在lg_order_1、lg_order_2、lg_user都创建district表
1 | mysql复制代码-- 区域表 |
- 在Sharding-JDBC的配置文件中指定公共表
1 | properties复制代码# 指定district为公共表 |
- 编写代码,操作公共表
- DistrictDao
1 | java复制代码@Mapper |
- DistrictDaoTest
1 | java复制代码@RunWith(SpringRunner.class) |
Sharding-JDBC读写分离
Sharding-JDBC读写分离则是根据SQL语义的分析,将读操作和写操作分别路由至主库与从库。它提供透明化读写分离,让使用方尽量像使用一个数据库一样使用主从数据库集群。
MySQL主从同步
为了实现Sharding-JDBC的读写分离,首先,要进行mysql的主从同步配置。
我们直接使用MyCat讲解中,在虚拟机上搭建的主从数据库
- 在主服务器中的test数据库创建商品表
1 | mysql复制代码CREATE TABLE products ( |
- 主库新建表之后,从库会根据binlog日志,同步创建
sharding-jdbc实现读写分离
- 配置数据源
1 | properties复制代码 |
- 配置主库与从库的相关信息
- ms1包含了m1和s1
1 | properties复制代码spring.shardingsphere.sharding.master-slave-rules.ms1.master-data-source-name=m1 |
- 配置数据节点
1 | properties复制代码#配置数据节点 |
- 编写测试代码
- ProductsDao
1 | java复制代码@Mapper |
- 测试
1 | java复制代码@RunWith(SpringRunner.class) |
本文转载自: 掘金