Sharding-JDBC实现读写分离

news2024/11/21 1:35:11

前言

快一个月没有更新文章了,太忙了太忙了,虽然慢了一点,但是我肯定不会断更。上一篇文章是《Mysql主从复制》,光是数据库层面的主从复制可不行,应用层面也是需要读写分离的,所以接上一篇文章我们来讲如何通过Sharding-JDBC实现应用读写分离

认识Sharding-sphere

遇到了什么问题

上一篇文章我们只是解决了数据库层面的主从复制,那么应用层面也需要做处理,就是把写操作打到主库,把读操作打到 从库,也就实现了读写分离了,如下图
在这里插入图片描述
那么如何才能够将业务中的读写请求路由到不同的读写库呢?想起刚出道那几年,我为了处理这个问题,自己基于SpringJDBC提供的AbstractRoutingDataSource,使用AOP+ThreadLocal技术自己封装到一套框架来实现读写分离,后来发现业界有更好的的框架已经解决了这个问题,如今能够实现读写分离的组件挺多,业界比较热门的介绍两款:MyCat , Sharding-sphere,今天主要是介绍如何使用Sharding-sphere来实现读写分离。

Sharding-sphere是啥

官网:http://shardingsphere.apache.org/index_zh.html

什么是 Apache ShardingSphere?
Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。

这句话看起来好像没有那么好理解,总之就是可以实现读写分离,数据库分片(分库分表),分布式事务支持等,也支持云原生。下图是它具备的能力,看起来很强大

在这里插入图片描述
这里还有一段对它的解释:

Apache ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 JDBC、Proxy 和 Sidecar(规划中)这 3 款相互独立,却又能够混合部署配合使用的产品组成。 它们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。

我们可以认为Sharding-sphere是一个关系型数据的分布式中间件。有三个部分组成,sharding-jdbc(JAVA),sharding-proxy(异构系统),Sharding-Sidecar(云原生)。

在这里插入图片描述

  • ShardingJDBC :sharding-jdbc 是一个开源的适用于微服务的分布式数据访问基础类库(jar),它始终以云原生的基础开发套件为目标。只支持java语言。sharding-jdbc完整的实现了分库分表/读写分离/分布式主键功能,并实现了柔性事务
    在这里插入图片描述

  • ShardingProxy :定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持,也就是支持多做开发语言的异构系统
    在这里插入图片描述

  • Sharding-Sidecar :定位为Kubernetes(k8s)或Mesos的云原生数据库代理,以DaemonSet的形式代理所有对数据库的访问。 通过无中心、零侵入的方案提供与数据库交互的的啮合层,即Database Mesh,又可称数据网格。

ShardingJDBC入门

文档:https://shardingsphere.apache.org/document/4.1.1/cn/manual/sharding-jdbc/usage/read-write-splitting/#%E5%9F%BA%E4%BA%8Espring-boot%E7%9A%84%E8%A7%84%E5%88%99%E9%85%8D%E7%BD%AE ;最新版本是5.x,我这里使用的是4.x来演示,如果想要使用最新版本,自己可以参考官方文档。

上面说到,ShardingJDBC是针对Java应用实现读写分离,或者分库分表支持,要使用他首先需要导入依赖,这里以SpringBoot 2.2.x版本作为演示

第一步:除了SpringBoot依赖之外,还需要导入sharding-jdbc依赖

<!-- 引入shardingjdbc -->
<dependency>
   <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-core-api</artifactId>
    <version>4.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.1.9</version>
</dependency>

解释:这里我排除了guava,会和SpringCloud中的guava包冲突 ,如果你没有出现依赖冲突可以不用排除,另外 这里使用了druid的连接池

第二步:配置读写分离

创建一个application.properties 配置文件,我有一个master和一个slave,所以加入内容:

#主,从数据库的名字,如果有更多的从,在后面继续加就可以
spring.shardingsphere.datasource.names=master,slave0

#主数据的链接信息
spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
#spring.shardingsphere.datasource.master.type=org.apache.commons.dbcp2.BasicDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.url=jdbc:mysql://localhost:3306/itsource-student
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=密码

#从数据库的链接 信息,如果有更多的从,在后面继续加就可以
spring.shardingsphere.datasource.slave0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave0.url=jdbc:mysql://localhost:3307/itsource-student
spring.shardingsphere.datasource.slave0.username=root
spring.shardingsphere.datasource.slave0.password=密码

#从数据库的负载均衡
spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
#集群名字
spring.shardingsphere.masterslave.name=ms
#主数据库名字,对应第一行的配置
spring.shardingsphere.masterslave.master-data-source-name=master
#多个从数据名字,逗号分隔
spring.shardingsphere.masterslave.slave-data-source-names=slave0
#是否打印sql
spring.shardingsphere.props.sql.show=true

这里就配置好了,ShardingJDBC会根据执行的是查询操作,或者增删改操作,然后自动选择配置中的主,从数据库。

第三部:启动测试

启动的时候就可以看到控制台日志:

16:32:55.914 [restartedMain] INFO 。。.ConfigurationLogger - [log,104] ..
loadBalanceAlgorithmType: round_robin
masterDataSourceName: master
name: ms
slaveDataSourceNames:
- slave0

当执行查询的时候可以从日志中看出是走的 slave0 ,而执行增删改的时候会走master。

16:36:21.140 [restartedMain] INFO 
 ShardingSphere-SQL - [log,74] - Actual SQL: slave0 ::: select ...

强制走主库

主从复制会出现一个问题,数据在主插入,读却是从从库读取,这个之间可能存在一定延迟,导致数据不一致,所以在实时性要求比较高的数据一般会强制要求走主库查询,我们可以做这样的设置

HintManager.clear();
try (HintManager hintManager = HintManager.getInstance()) {
	//设置走主库
   	hintManager.setMasterRouteOnly();
   	return xxMapper.selectList();
}

然后测试观察控制台,看得出查询是走了主库 master 了

16:45:32.320 [http-nio-8080-exec-9] INFO  
ShardingSphere-SQL - [log,74] - Actual SQL: master ::: select ...

当然这样比价麻烦,因为每次要走主库都要添加这一段代码,比较好的处理方式是使用AOP来解决。

第一步:定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface DataSourceMaster {
}

第二步:定义AOP切面,获取方法上的DataSourceMaster 来设置走主库

@Slf4j
@Component
@Aspect
public class DataSourceMasterAop {

    @Around("execution(* cn.itsource.service.impl.*.*(..))")
    public Object master(ProceedingJoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        Object ret = null;

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        DataSourceMaster shardingJdbcMaster = method.getAnnotation(DataSourceMaster.class);

        HintManager hintManager = null;
        try {
            if (Objects.nonNull(shardingJdbcMaster)) {
                HintManager.clear();
                hintManager = HintManager.getInstance();
                hintManager.setMasterRouteOnly();
            }
            ret = joinPoint.proceed(args);
        }catch (Exception ex){
            log.error("exception error",ex);
        }finally {
            if (Objects.nonNull(shardingJdbcMaster) && Objects.nonNull(hintManager)) {
                hintManager.close();
            }
        }
        return ret;
    }
}

第三步:在方法上贴注解即可

@DataSourceMaster
 public List<Xxx> selectList(){
	return XxxMapper.selectList();
 }

好了,文章就写到这里咯,喜欢的话请一定给个好评,你的肯定是我最大的动力哦~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

赶紧进来看看---万字博客详解C/C++中的动态内存管理

本篇博客主要介绍了C/C程序内部的内存开辟.动态内存分布 动态内存函数malloc calloc realloc free的使用 常见的动态内存错误.以及柔性数组的概念与使用 学会动态内存管理将不再局限于使用静态的空间,对内存空间的理解和使用将更进一层楼~ C/C动态内存管理一.认识C/C程序的内存…

【C++升级之路】类与对象(中)

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;类与对象知识汇总&#xff0c;包括6大默认成员函数、日期类的实现 &#x1f6a2;&#x1f6a2;作者简介&…

graphQL入门分享

是什么 一种用于 API 的查询语言&#xff1b;它与特定技术无关&#xff0c;你可以用任何语言实现它 简单理解&#xff0c;他能提供一个接口&#xff0c;让我们来调用&#xff0c;只是返回的数据格式更多是由我们前端来控制 为什么 官网&#xff1a;https://graphql.cn/ 1.请求你…

深入理解计算机系统前篇总结

&#x1f343;博主昵称&#xff1a;一拳必胜客 博主主页面链接&#xff1a;博主主页传送门 博主专栏页面连接&#xff1a;专栏传送门–计算机考研 &#x1f351;创作初心&#xff1a;本博客的初心是每天分享记录自己学习的脚步&#xff0c;和各位技术友探讨交流&#xff0c;同时…

惠州龙门大米飘香 国稻种芯-中国水稻节:广东乡村振兴样板

惠州龙门大米飘香 国稻种芯-中国水稻节&#xff1a;广东乡村振兴样板 人民日报客户端 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 中国农民丰收节国际贸易促进会 国稻种芯中国水稻节 中国三农智库网-功能性农业农业大健康大会报道&#xff1a; 粒粒“龙门大米”精美飘…

百度地图API的使用(附案例)

文章目录JavaScript API GL一、申请秘钥Hello World显示地址案例定位功能步行导航搜索功能地铁路线规划JavaScript API GL 百度地图JavaScript API是一套由JavaScript语言编写的应用程序接口&#xff0c;可帮助您在网站中构建功能丰富、交互性强的地图应用&#xff0c;支持PC端…

经典文献阅读之--用于自动驾驶的高清地图生成技术

0. 简介 这篇文章我们介绍一下论文“High-Definition Map Generation Technologies For Autonomous Driving: A Review“&#xff0c;2022年6月11日&#xff0c;来自加拿大Ontario Tech University。相较于网上的其他文章&#xff0c;本文更在意向读者更轻松全面的了解文章中介…

【Web前端大作业】基于HTML+CSS+JavaScript制作西北大学新闻网站(7页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

悬浮坐标解决方案:如何在图片获取xy鼠标位置和增加标注信息

悬浮坐标的定义&#xff0c;基于固定分辨率的图片&#xff0c;通过获取该图片x和y坐标确定位置后并添加标注&#xff0c;实现位置展示、对应图片内物品展示的一种标注开发方式。 技术要点 自动获取图片x和y坐标&#xff1b;将多个坐标xy在图片上通过CSS定位的方式予以展示&am…

pytorch学习(三)——模型层

文章目录1. 自定义模型层2. 使用预训练模型3. 模型构建风格3.1 使用 add_module 方法3.2 添加进 Sequential3.3 Sequential作为模型容器3.4 ModuleList作为模型容器3.5 ModuleDict作为模型容器当我们构建了数据管道能够将数据一个batch一个batch的取出来后&#xff0c;下一步就…

微信小程序函数处理之保姆级讲解

目录 生命周期函数 生命周期函数的调用过程 页面事件函数 页面路由管理 自定义函数 setData设值函数 生命周期函数 在使用Page&#xff08;&#xff09;构造器注册页面时&#xff0c;需要使用生命周期函数&#xff0c;包括onLoad&#xff08;&#xff09;页面加载时生命周…

硬件工程师成长之路(10.1)——芯片选型

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录前言一、电机驱动类1 、直流电机驱动芯片2、步进电机③、资料前言 送给大学毕业后找不到奋斗方向的你&#xff08;每周…

【车间调度】基于全球邻域和爬坡来优化模糊柔性作业车间调度问题(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑…

VS Studio 搭建跨平台开发环境

VS Studio 搭建跨平台开发环境 增加VS的工作负载 打开Visual Studio Installer 安装器&#xff0c;点击修改 在这个界面找到Linux开发环境&#xff0c;勾上然后在点击右下角的修改等待安装。我的是因为已经有了所以下面那里显示的是关闭&#xff0c;没有的是显示的修改 等待安…

LabVIEW强制重新安装无法运行或损坏的NI软件

LabVIEW强制重新安装无法运行或损坏的NI软件 可以参考附件的录像说明。LabVIEW强制重新安装无法运行或损坏的NI软件 - 北京瀚文网星科技有限公司 (bjcyck.com) 某些NI软件&#xff0c;工具包或驱动程序已损坏&#xff0c;损坏或无法按预期运行&#xff0c;想尝试重新安装以进…

【ArchSummit】众安金融微服务架构演进实战

前言 &#x1f4eb; 作者简介&#xff1a;小明java问道之路&#xff0c;专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码&#xff0c;就职于大型金融公司后端高级工程师&#xff0c;擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &a…

网络原理——传输层_UDP

JavaEE传送门JavaEE JavaEE——No.2 套接字编程(TCP) JavaEE——网络原理_应用层 目录传输层UDP传输层 端到端之间的传输, 重点关注的是起点和终点 核心的协议有两个: UDP: 无连接, 不可靠传输,面向数据报, 全双工 TCP: 有链接, 可靠传输, 面向字节流, 全双工 UDP UDP协议…

nginx+tomcat(二)

四层代理: 四层代理: 一般使用七层代理也就是http应用层代理&#xff0c;可以反向代理和负载均衡。但是项目要使用长连接&#xff0c;此时内网服务器肯定不能暴漏&#xff0c;还是需要接入层网关进行转发&#xff0c;一般有使用lvs&#xff0c;lvs专门用作四层代理和负载均衡基…

【C++】模板初阶

文章目录一、泛型编程二、函数模板1、概念与格式2、底层原理3、实例化4、参数的匹配规则三、类模板1、概念与格式2、实例化一、泛型编程 我们通过实现一个通用的交换函数来引入泛型编程&#xff1a; void Swap(int& left, int& right) {int temp left;left right;r…

Linux 命令(147) —— truncate 命令

文章目录1.命令简介2.命令格式3.选项说明4.常用示例参考文献1.命令简介 truncate 将文件的大小缩小或扩展到指定的大小。 如果指定的文件不存在将被创建。 如果文件大于指定的大小&#xff0c;则会丢失额外的数据。如果较短&#xff0c;它将被扩展&#xff0c;扩展的稀疏部分…