ShardingSphere数据库读写分离
码农在囧途
最近这段时间来经历了太多东西,无论是个人的压力还是个人和团队失误所带来的损失,都太多,被骂了很多,也被检讨,甚至一些不方便说的东西都经历了,不过还好,一切都得到了解决,无论好坏,这对于个人来说也是一种成长吧,事后自己也做了一些深刻的检讨,总结为一句话“挫败使你难受,使你睡不着觉,使你痛苦,不过最后一定会使你变得成熟,变得认真,变得负责”,每次面临挫败,我都会告诉自己,这不算什么,十年之后,你回过头来看待这件事的时候,你一定会觉得,这算什么屁事。
背景
在现在这个数据量与日俱增的时代,传统的单表,单库已经无法满足我们的需求,可能早期数据量不是很大,CRUD都集中在一个库中,但是当数据量 到达一定的规模的时候,使用单库可能就无法满足需求了,在实际场景中,读的频率是远远大于写的,所以我们一般会做读写分离,主库一般用于写,而从库 用于读,而主从分离有好几种模式。
一主多从
一主多从是只有一台主机用于写操作,多台从机用于读操作,一主多从是存在风险的,当主机宕机后,那么写服务就会瘫痪,本文我们主要说的是ShardingSphere读写分离, 而目前ShardingSphere只支持单主库,所以如果要保证业务的高可用,那么目前ShardingSphere不是很好的选择,不过希望ShardingSphere后面支持多主机模式。
多主多从
从上面的一主多从我们看出了它的弊端,所以为了保证高可用,我们可能需要多个主机用于写操作,这样当某个主机宕机,其他主机还能继续工作,ShardingSphere只支持 单主机。
ShardingSphere只需要简单的配置就能实现数据库的读写的分离,我们甚至感知不到是在操作多个数据库,极大的简化了我们的开发,但是ShardingSphere 不支持多主库,也无法进行主从数据库的同步。
ShardingSphere整合SpringBoot项目进行主从分离
ShardingSphere和SpringBoot能够很简单的进行组合,只需要简单的配置,ShardingSphere能够和主流的ORM框架进行整合,ShardingSphere会 从ORM框架中解析出SQL语句,判断是读操作还是写操作,如果是读操作,则会落到主库上,如果是读操作,那么ShardingSphere会使用对应的负载均衡算法负载到 对应的从库上面。
maven引入ShardingSphere starter
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.2</version>
</dependency>
yml文件配置
names
为数据库名称字符串,然后需要一个一个的进行配置JDBC连接,对于读写分离,我们需要关注rules下面的readwrite-splitting
通过load-balancers
配置负载均衡策略,data-sources
配置对应的读写库,目前ShardingSphere只支持单主库,多从库,如下我们写 库使用write-data-source-name
,库为db1
,读库使用read-data-source-names
,库db2
,db3
,db4
。
spring:
shardingsphere:
datasource:
names: db1,db2,db3,db4
db1:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: qwer123@
type: com.zaxxer.hikari.HikariDataSource
maximumPoolSize: 10
db2:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: qwer123@
type: com.zaxxer.hikari.HikariDataSource
maximumPoolSize: 10
db3:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: qwer123@
type: com.zaxxer.hikari.HikariDataSource
maximumPoolSize: 10
db4:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/db4?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: qwer123@
type: com.zaxxer.hikari.HikariDataSource
maximumPoolSize: 10
rules:
sharding:
readwrite-splitting:
load-balancers:
round_robin:
type: ROUND_ROBIN
data-sources:
read_write_db:
type: Static
props:
write-data-source-name: db1
read-data-source-names: db2,db3,db4
load-balancer-name: round_robin
props:
sql-show: true
测试写操作。
因为写操作配置的数据库是db1
,所以所有写操作都应该进入db1
,如下图所示,解析出来的ShardingSphere-SQL
中显示的都是db1。
测试读操作
读操作配置的数据库是db2
,db3
,db4
,配置的负载均衡算法是ROUND_ROBIN
(轮询算法),所以查询请求会在三个库顺序查询。
ShardingSphere负载均衡算法
因为从库有多个,所以我们需要根据一定的策略将请求分发到不同的数据库上,防止单节点的压力过大或者空闲,ShardingSphere内置了多种负载均衡算法,如果我们想实现自己的 算法,那么可以实现ReadQueryLoadBalanceAlgorithm
接口,下面我们列举几种来看下。
ROUND_ROBIN 轮询算法
配置负载均衡算法为轮询算法,那么所有请求都会均匀的分发到对应的数据库,这样,每台数据库所承受的压力都是一样的,轮询算法对应的实现类是RoundRobinReplicaLoadBalanceAlgorithm
。
public final class RoundRobinReplicaLoadBalanceAlgorithm implements ReadQueryLoadBalanceAlgorithm {
private final AtomicInteger count = new AtomicInteger(0);
@Getter
private Properties props;
@Override
public void init(final Properties props) {
this.props = props;
}
@Override
public String getDataSource(final String name, final String writeDataSourceName, final List<String> readDataSourceNames) {
if (TransactionHolder.isTransaction()) {
return writeDataSourceName;
}
return readDataSourceNames.get(Math.abs(count.getAndIncrement()) % readDataSourceNames.size());
}
@Override
public String getType() {
return "ROUND_ROBIN";
}
@Override
public boolean isDefault() {
return true;
}
}
RANDOM 随机算法
如果使用随机算法,那么请求过来以后就会随机的分发到其中的一个数据库上面,使用随机算法可能会导致请求的分发不均匀,可能某一台 接受到了大量的请求,某一台接受到的请求相对来说较少。
WEIGHT 基于权重的算法
基于权重的算法需要做相应的配置,我们可以将某一台数据库的权重加大,某一台数据库的权重减小,这样,权重大的数据库 就会接收到更多的请求,权重小的接收到的请求就会比较少。
在ShardingSphere中自定义负载均衡算法
ShardingSphere中使用了大量的SPI
,所以我们开发者可以自由的实现自己的规则,然后无缝的切换到自己的规则,我们可以实现自己的一套负载均衡算法,其实ShardingSphere内置的集中负载均衡算法完全能满足数据库负载均衡,只不过为了更加深入的学习ShardingSphere,所以我们很有必要自己简单的实现一下。
下面我们简单的实现一下,我们就不去实现一些复杂的了,为了演示,我们将所有请求全部都负载到db2
。
定义SPI
我们从ShardingSphere的读写分离模块shardingspere-readwrite-spliltting-core
中的META-INF/services下面看到了负载均衡的SPI。
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.RoundRobinReplicaLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.RandomReplicaLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.WeightReplicaLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.FixedPrimaryLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.FixedReplicaRandomLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.FixedReplicaRoundRobinLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.FixedReplicaWeightLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.TransactionRandomReplicaLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.TransactionRoundRobinReplicaLoadBalanceAlgorithm
org.apache.shardingsphere.readwritesplitting.algorithm.loadbalance.TransactionWeightReplicaLoadBalanceAlgorithm
为了实现自己的负载均衡算法,我们需要在自己的模块中定义SPI,如下,在自己项目的META-INF/services目录下编写负载均衡SPI接口,里面内容为我们自定义的负载均衡算法的类文件的位置。
编写负载均衡算法核心代码
自定义负载均衡算法需要实现ReadQueryLoadBalanceAlgorithm
接口,里面核心的两个方法是getDataSource
和getType
,getDataSource
是算法的逻辑实现部分,其目的是选出一个目标数据库,此方法会传入readDataSourceNames
,它是读库的集合,我们此处直接返回db2
,那么会一直读db2
,getType
是返回负载均衡算法的名称。
/**
* 功能说明: 自定义负载均衡算法
* <p>
* Original @Author: steakliu-刘牌, 2022-07-20 18:05
* <p>
* Copyright (C)2020-2022 steakliu All rights reserved.
*/
public class CustomReplicaLoadBalanceAlgorithm implements ReadQueryLoadBalanceAlgorithm {
@Getter
private Properties props;
@Override
public String getDataSource(final String name, final String writeDataSourceName, final List<String> readDataSourceNames) {
return "db2";
}
@Override
public String getType() {
return "CUSTOM";
}
@Override
public void init(Properties props) {
this.props = props;
}
@Override
public boolean isDefault() {
return false;
}
}
在yml中使用自己实现的负载均衡算法
rules:
sharding:
readwrite-splitting:
load-balancers:
custom:
type: CUSTOM
data-sources:
read_write_db:
type: Static
props:
write-data-source-name: db1
read-data-source-names: db2,db3,db4
load-balancer-name: custom
发起大量的查询操作
从日志输出来看,所有的请求全部落在了db2
上面,于是证明我们自定义的负载均衡算法成功了。
读写分离的中间件其实有很多,ShardingSphere旨在构建异构数据库上层的标准和生态,使用它我们基本上能解决数据库中的大部分问题,但是ShardingSphere也并不是万能的,还有一些东西没有实现,我们期待ShardingSphere能够实现更多强大,好用的功能。
关于ShardingSphere读写分离的分享,我们今天就先说到这里,后面我们会继续探索ShardingSphere的更多强大的功能,比如数据分片,高可用,数据加密,影子库等,今天的分享就到这里,感谢你的观看,我们下期见。
ShardingSphere数据库读写分离的更多相关文章
- 分库分表(3) ---SpringBoot + ShardingSphere 实现读写分离
分库分表(3)---ShardingSphere实现读写分离 有关ShardingSphere概念前面写了两篇博客: 1.分库分表(1) --- 理论 2. 分库分表(2) --- ShardingS ...
- Spring aop应用之实现数据库读写分离
Spring加Mybatis实现MySQL数据库主从读写分离 ,实现的原理是配置了多套数据源,相应的sqlsessionfactory,transactionmanager和事务代理各配置了一套,如果 ...
- CYQ.Data V5 数据库读写分离功能介绍
前言 好多年没写关于此框架的新功能的介绍了,这些年一直在默默地更新,从Nuget上的记录就可以看出来: 这几天在看Java的一些东西,除了觉的Java和.NET的相似度实在太高之外,就是Java太原始 ...
- ThinkPHP v3.2.3 数据库读写分离,开启事务时报错:There is no active transaction
如题:ThinkPHP v3.2.3 数据库读写分离,开启事务时报错: ERR: There is no active transaction 刚开始以为是数据表引擎不对造成的,因为 有几张表的引擎是 ...
- EF架构~通过EF6的DbCommand拦截器来实现数据库读写分离~终结~配置的优化和事务里读写的统一
回到目录 本讲是通过DbCommand拦截器来实现读写分离的最后一讲,对之前几篇文章做了一个优化,无论是程序可读性还是实用性上都有一个提升,在配置信息这块,去除了字符串方式的拼接,取而代之的是sect ...
- 161220、使用Spring AOP实现MySQL数据库读写分离案例分析
一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...
- [转]Spring数据库读写分离
数据库的读写分离简单的说是把对数据库的读和写操作分开对应不同的数据库服务器,这样能有效地减轻数据库压力,也能减轻io压力. 主(master)数据库提供写操作,从(slave)数据库提供读操作,其实在 ...
- spring+mybatis利用interceptor(plugin)兑现数据库读写分离
使用spring的动态路由实现数据库负载均衡 系统中存在的多台服务器是"地位相当"的,不过,同一时间他们都处于活动(Active)状态,处于负载均衡等因素考虑,数据访问请求需要在这 ...
- 学会数据库读写分离、分表分库——用Mycat,这一篇就够了!
系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优化也是非常重要的.主从.热备.分表分库等都是系统发展迟早会遇到的技术问题问题.Mycat是一 ...
随机推荐
- spring boot redis 写入异常
redis 的 key value 使用 json 序列化.反序列化时,写入的 bean 不能是 final 类型的类,否则无法解析
- Spring Security之用户名+密码登录
自定义用户认证逻辑 处理用户信息获取逻辑 实现UserDetailsService接口 @Service public class MyUserDetailsService implements Us ...
- MySQL启动与多实例安装
启动方式及故障排查 一.几个问题 1.1 /etc/init.d/mysql 从哪来 cp /usr/local/mysql/support-files/mysql.server /etc/init. ...
- 什么是请求参数、表单参数、url参数、header参数、Cookie参数?一文讲懂
最近在工作中对 http 的请求参数解析有了进一步的认识,写个小短文记录一下. 回顾下自己的情况,大概就是:有点点网络及编程基础,只需要加深一点点对 HTTP 协议的理解就能弄明白了. 先分享一个小故 ...
- DOM获取元素、修改元素
## DOM获取元素.修改元素### 1.DOM#### ①什么是DOM?作用? > DOM是文档对象模型 > 作用:操作网页内容,可以开发网页内容特效和实现用户交互.#### ②DOM对 ...
- 官方出品,比 mydumper 更快的逻辑备份工具
mysqldump 和 mydumper 是我们常用的两个逻辑备份工具. 无论是 mysqldump 还是 mydumper 都是将备份数据通过 INSERT 的方式写入到备份文件中. 恢复时,myl ...
- 【多线程与高并发原理篇:4_深入理解synchronized】
1. 前言 越是简单的东西,在深入了解后发现越复杂.想起了曾在初中阶段,语文老师给我们解说<论语>的道理,顺便给我们提了一句,说老子的无为思想比较消极,学生时代不要太关注.现在有了一定的生 ...
- Similarity calculation
推荐算法入门(相似度计算方法大全) 一.协同过滤算法简介 在推荐系统的众多方法之中,基于用户的协同过滤是诞最早的,原理也比较简单.基于协同过滤的推荐算法被广泛的运用在推荐系统中,比如影视推荐.猜你喜欢 ...
- python实现对简单的运算型验证码的识别【不使用OpenCV】
最近在写我们学校的教务系统的手机版,在前端用户执行绑定操作后,服务器将执行登录,但在登录过程中,教务系统中有个运算型的验证码,大致是这个样子的: 下面我们开始实现这个验证码的识别. 1.图片读取 从网 ...
- Jenkins之配置GitHub-Webhook
前提条件1: 运行Jenkins的机器需要安装git,并且git.exe文件在系统的环境变量里面,或者手动在 Manage Jenkins -> Global Tool Configuratio ...