一套开源的分布式数据库中间件解决方案
有三个产品:Sharding-JDBC 和 Sharding-Proxy
定位为关系型数据库中间件,合理在分布式环境下使用关系型数据库操作
开发中遇到的问题:
数据库数据量不可控的,随着时间和业务发展,造成表里面数据越来越多,如果再去对数
据库表 curd 操作时候,造成性能问题。
**方案一:**从硬件方面,加CPU加服务器等,缺点是成本高,维护麻烦。
**方案二:**进行分库分表处理。
分库分表有两种方式:垂直切分和水平切分
垂直分库、垂直分表:
操作数据库中某张表,把这张表中一部分字段数据存到一张新表里面,再把这张表另一部分字段数据存到另外一张表里面,例如:一张表中有7个字段,将4个字段存到一张表,剩下3个存到另一张表中,这种操作就叫做垂直分表。
将数据库根据业务进行划分,专库专表,这种操作就叫做垂直分库。
水平分库、水平分表:
水平分表就是将创建一个与业务表相同的表,在进行数据操作的时候可以根据某些条件进行判断去操作哪张表,就像是复制出几个相同的表,这样在数据量大的情况下减少了操作数据库的压力。水平分库也是类似于复制。
实际开发中的应用:
在数据库设计时候考虑垂直分库和垂直分表 。
随着数据库数据量增加,不要马上考虑做水平切分,首先考虑缓存处理,读写分离,使
用索引等等方式,如果这些方式不能根本解决问题了,再考虑做水平分库和水平分表 。
分库分表问题:
跨节点连接查询问题(分页、排序)
多数据源管理问题
一、创建数据库并在数据库中创建两张字段相同的表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9AUYadqE-1670315836922)(C:\Users\52962\AppData\Roaming\Typora\typora-user-images\1670295502651.png)]
二、创建SpringBoot项目并引入相关依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
三、配置文件
这里使用的是properties类型的配置文件,查看官网目前只有yaml文件类型的配置,这个待尝试。
# shardingjdbc 分片策略
# 配置数据源,给数据源起名称
spring.shardingsphere.datasource.names=master
#解决一个实体类对应两张表
spring.main.allow-bean-definition-overriding=true
# 配置数据源,这里使用阿里的德鲁伊数据源
spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master.url=jdbc:mysql://121.xx.xx.xxx:3306/course_db?characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=root
#指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 master.course_1 ,master.course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=master.course_$->{1..2}
# 指定 course 表里面主键 cid 生成策略 SNOWFLAKE,雪花算法
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE
# 指定分片策略 约定 cid 值偶数添加到 course_1 表,如果 cid 是奇数添加到 course_2表
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid % 2 + 1}
# 打开 sql 输出日志
spring.shardingsphere.props.sql.show=true
四、数据表中插入数据
@Test
void insertCourse() {
for (int i = 0; i < 10; i++) {
Course course = new Course();
course.setCname("测试数据" + i);
course.setUserId(333445L);
course.setCstaus("测试状态" + i);
courseService.save(course);
}
}
插入数据效果如下,id为偶数的插入到了1表中,为奇数的插入到了2表中,达到了理想效果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6V1sm5Kc-1670315836924)(C:\Users\52962\AppData\Roaming\Typora\typora-user-images\1670296529597.png)]
五、遇到的问题
(1)启动时报如下图所示的错误,出现这个问题的原因是因为我们创建了一个实体类,而它对应着两张表,spring提示我们要么重新命名要么进行覆盖配置,我们选择配置。在配置文件中添加:
#解决一个实体类对应两张表
spring.main.allow-bean-definition-overriding=true
报错图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CLKIuvxL-1670315836924)(C:\Users\52962\AppData\Roaming\Typora\typora-user-images\1670294423736.png)]
(2)修改完实体类的问题,启动项目又报了如下错误,原因是因为我们在设置数据源的url时没有配置全面,配置应该如下图所示,其中"characterEncoding=UTF-8"为配置字符集编码,设置"useSSL=false",SSL即为:Secure Sockets Layer 安全套接字协议。如果MySQL的版本是5.7之后的版本必须要加上useSSL=false,mysql5.7以及之前的版本则不用进行添加useSSL=false,会默认为false,一般情况下都是使用useSSL=false,尤其是在将项目部署到linux上时要使用useSSL=false。
useSSL=true:就是一般通过证书或者令牌进行安全验证
useSSL=false:就是通过账号密码进行连接
"serverTimezone=Asia/Shanghai"为设置时区,MySQL8.0以上版本,url需要添加时区。
以上就是解决问题的方法,具体配置如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Ju0ISKU-1670315836925)(C:\Users\52962\AppData\Roaming\Typora\typora-user-images\1670294971105.png)]
报错图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6DTD83d-1670315836925)(C:\Users\52962\AppData\Roaming\Typora\typora-user-images\1670295176183.png)]
数据库创建两个数据库db1和db2并且每个都创建两个字段相同的表,代码只需要修改配置文件即可,在上面操作的基础上进行修改。
配置文件如下
spring.shardingsphere.datasource.names=master1,master2
#解决一个实体类对应两张表
spring.main.allow-bean-definition-overriding=true
# 配置数据源,这里使用阿里的德鲁伊数据源
spring.shardingsphere.datasource.master1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master1.url=jdbc:mysql://121.4.49.xx:3306/db1?characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.master1.username=root
spring.shardingsphere.datasource.master1.password=root
spring.shardingsphere.datasource.master2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master2.url=jdbc:mysql://121.4.49.xx:3306/db2?characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.master2.username=root
spring.shardingsphere.datasource.master2.password=root
#指定 course 表分布情况,配置表在哪个数据库里面,表名称都是什么 master.course_1 ,master.course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=master$->{1..2}.course_$->{1..2}
# 指定 course 表里面主键 cid 生成策略 SNOWFLAKE,雪花算法
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE
# 指定分片策略 约定 cid 值偶数添加到 course_1 表,如果 cid 是奇数添加到 course_2表
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid % 2 + 1}
# 指定数据库分片策略
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=master$->{user_id % 2 + 1}
# 打开 sql 输出日志
spring.shardingsphere.props.sql.show=true
垂直分库和垂直分表也都是进行类似的配置,可以参考官方文档:
https://shardingsphere.apache.org/document/current/cn/overview/
什么是读写分离?
读写分离就是让主数据库进行事务性操作,增、删、改操作,让从数据库进行查询操作。数据库将主数据库中的事务性操作数据同步到其他从数据库当中。原理是从库监听binlog日志,将对进行的增删改操作进行同步。
表也都是进行类似的配置,可以参考官方文档:
https://shardingsphere.apache.org/document/current/cn/overview/
什么是读写分离?
读写分离就是让主数据库进行事务性操作,增、删、改操作,让从数据库进行查询操作。数据库将主数据库中的事务性操作数据同步到其他从数据库当中。原理是从库监听binlog日志,将对进行的增删改操作进行同步。