Sharding-JDBC是当当网的一个开源项目,只需引入jar即可轻松实现读写分离与分库分表。
读写分离,简单来说,就是将DML交给主数据库去执行,将更新结果同步至各个从数据库保持主从数据一致,DQL分发给从数据库去查询,从数据库只提供读取查询操作。读写分离特别适用于读多写少的场景下,通过分散读写到不同的数据库实例上来提高性能,缓解单机数据库的压力。

前期准备

三个数据库,一个主库 ,两个备份库 ,在此之前实现主从同步。

一、创建spring boot项目,加入相关pom jar包

<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId>dependency><dependency><groupId>org.mybatis.spring.bootgroupId><artifactId>mybatis-spring-boot-starterartifactId><version>1.3.2version>dependency><dependency><groupId>mysqlgroupId><artifactId>mysql-connector-javaartifactId>dependency><dependency><groupId>com.alibabagroupId><artifactId>druid-spring-boot-starterartifactId><version>1.1.10version>dependency><dependency><groupId>org.projectlombokgroupId><artifactId>lombokartifactId>dependency><dependency><groupId>io.shardingspheregroupId><artifactId>sharding-jdbc-spring-boot-starterartifactId><version>3.1.0.M1version>dependency>

二、配置相关配置文件

sharding:jdbc:dataSource:names: db-test0,db-test1,db-test2# 配置主库db-test0: #org.apache.tomcat.jdbc.pool.DataSourcetype: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://10.12.12.12:3304/test_master?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTusername: rootpassword:#最大连接数maxPoolSize: 20db-test1: # 配置第一个从库type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://10.12.12.12:3304/test_slave01?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMTusername: rootpassword:maxPoolSize: 20db-test2: # 配置第二个从库type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://10.12.12.12:3304/test_slave02?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMTusername: rootpassword:maxPoolSize: 20config:masterslave: # 配置读写分离load-balance-algorithm-type: round_robin # 配置从库选择策略,提供轮询与随机,这里选择用轮询//random 随机 //round_robin 轮询name: db1s2master-data-source-name: db-test0slave-data-source-names: db-test1,db-test2props:sql: # 开启SQL显示,默认值: false,注意:仅配置读写分离时不会打印日志!!!show: trueserver:port: 8081

三、接下来我们测试下

1、先准备三个库,和一个表

CREATE TABLE `user` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT,`name` VARCHAR(255) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=INNODB

2、编写一个insert、和select的方法

UserMapper

public interface UserMapper {@Insert({ " })Integer createUser(@Param("user") User user);@Select({ "select * from user" })ListgetUserList();}

UserController

@RestControllerpublic class UserController {@AutowiredUserService userService;@PostMapping("/create")public Integer createUser(@RequestBody User user) {return userService.createUser(user);}@GetMapping("/getList")public ListgetUserList() {return userService.getUserList();}}

3、通过postman测试

为了方便测试,我把三个库的数据制造成不一样的。

1)首先测试insert的

  • 这时候,我们查看三个库,只发现主库,新增了数据,其他的库没有新增数据。

2)测试查询

我们先备份库01的数据写入为 {"id":2,"name":"2"},备份库02的数据写入为 {"id":3,"name":"3"}

  • 我们多次查询,可以发现备份库的数据在轮询查出。

四、说明

1)原理说明
  先看下SQL语言四大分类:DQL、DML、DDL、DCL。

  • DQL(Data QueryLanguage):数据查询语言,比如select查询语句

  • DML(Data Manipulation Language):数据操纵语言,比如insert、- - delete、update更新语句

  • DDL():数据定义语言,比如create/drop/alter等语句

  • DCL():数据控制语言,比如grant/rollback/commit等语句

追溯源码进入MasterSlaveDataSource这个类中

/** * Get data source from master-slave data source. * * @param sqlType SQL type * @return data source from master-slave data source */public NamedDataSource getDataSource(final SQLType sqlType) {if (isMasterRoute(sqlType)) {DML_FLAG.set(true);return new NamedDataSource(masterSlaveRule.getMasterDataSourceName(), masterSlaveRule.getMasterDataSource());}String selectedSourceName = masterSlaveRule.getStrategy().getDataSource(masterSlaveRule.getName(),masterSlaveRule.getMasterDataSourceName(), new ArrayList<>(masterSlaveRule.getSlaveDataSourceMap().keySet()));DataSource selectedSource = selectedSourceName.equals(masterSlaveRule.getMasterDataSourceName())? masterSlaveRule.getMasterDataSource() : masterSlaveRule.getSlaveDataSourceMap().get(selectedSourceName);Preconditions.checkNotNull(selectedSource, "");return new NamedDataSource(selectedSourceName, selectedSource);}private boolean isMasterRoute(final SQLType sqlType) {return SQLType.DQL != sqlType || DML_FLAG.get() || HintManagerHolder.isMasterRouteOnly();}

  • isMasterRoute() 方法判断当前操作是否应该路由到主库数据源,如果SQL类型是DML则返回true

  • getDataSource() 方法根据SQL类型返回一个数据源。如果SQL类型是DQL则通过配置的算法返回一个从库数据源,如果SQL类型是DML则返回主库数据源。
    2)轮询策略源码分析

/** * Round-robin slave database load-balance algorithm. * * @author zhangliang */public final class RoundRobinMasterSlaveLoadBalanceAlgorithm implements MasterSlaveLoadBalanceAlgorithm {private static final ConcurrentHashMap COUNT_MAP = new ConcurrentHashMap<>();@Overridepublic String getDataSource(final String name, final String masterDataSourceName, final List slaveDataSourceNames) {AtomicInteger count = COUNT_MAP.containsKey(name) ? COUNT_MAP.get(name) : new AtomicInteger(0);COUNT_MAP.putIfAbsent(name, count);count.compareAndSet(slaveDataSourceNames.size(), 0);return slaveDataSourceNames.get(count.getAndIncrement() % slaveDataSourceNames.size());}

其内部通过并发容器ConcurrentHashMap与AtomicInteger的CAS保障高并发下计数线程安全,使用无锁的方式比加锁效率更高。

  • 这样,我们就可以编写自己的策略了

sharding:jdbc:config:masterslave:load-balance-algorithm-class-name: 自定义算法类的全限定名

2)注意点

  • Sharding-JDBC目前仅支持一主多从的结构

  • Sharding-JDBC没有提供主从同步的实现,该功能需要自己额外搭建,可参照《基于Docker搭建MySQL主从复制》简易搭建测试使用

  • 主库和从库的数据同步延迟导致的数据不一致问题需要自己去解决

  • Sharding-JDBC虽然提供了打印SQL日志的开关,但是如果仅配置了读写分离好像是没有用的

  • 文中配置使用的是HikariCP连接池,使用其他连接池时,需要将jdbc-url配置名该为url,否则可能会抛异常

springboot 读写分离_springboot +ShardingJDBC 读写分离相关推荐

  1. Sharding-JDBC读写分离探秘

    前段时间写了篇如何使用Sharding-JDBC进行分库分表的例子,相信能够感受到Sharding-JDBC的强大了,而且使用配置都非常干净.官方支持的功能还包括读写分离.分布式主键.强制路由等.这里 ...

  2. mysql的读写分离技术_mysql 读写分离方法

    数据库的读写分离方案很多,这里介绍基于mysql数据库的读写分离方案. 比较常见的读写分离方案如下: 1 基于查询分离 最简单的分离方法是将读和写分发到主和从服务器上,这种策略很容易实现,但是仅限于一 ...

  3. (2022)Springboot+vue3项目开发前后端分离书法图书管理Coun

    项目地址:https://github.com/KKJava1/Coun Coun是基于Springboot+vue3 项目采用了前后端分离技术:后端采用 springBoot 基本框架,数据库连接池 ...

  4. 在Docker 上完成对Springboot+Mysql+Redis的前后端分离项目的部署(全流程,全截图)

    本文章全部阅读大约2小时,包含一个完整的springboot + vue +mysql+redis前后端分离项目的部署在docker上的全流程,比较复杂,请做好心理准备,遇到问题可留言或则私信 目录 ...

  5. 利用SpringBoot和Vue实现前后端分离(附源码)

    利用SpringBoot和Vue实现前后端分离(附源码) 引言: 本文主要分享了SpringBoot和Vue整合实现前后端分离,实现了简单的增删查改:包括:项目的搭建.后端的实现.前台的实现:(附源码 ...

  6. Java权限管理|基于springBoot+springSecurity+jwt实现前后端分离用户权限认证

    基于springBoot+springSecurity+jwt实现前后端分离用户权限认证 1. 项目说明   主要基于前后端分离情况下用户权限认证, 当用户登录认证成功后,每个用户会获取到自己的tok ...

  7. 基于Springboot+MybatisPlus+Vue的前后端分离电子商城系统

    一.基于Springboot+MybatisPlus+Vue的前后端分离电子商城系统 基于Springboot+MybatisPlus+Vue的前后端分离电子商城系统,主要分为用户端和管理端两个模块. ...

  8. 使用SpringBoot + Vue (若依前后端分离版) 写项目的一些总结(持续更新...)

    使用SpringBoot + Vue(若依前后端分离版) 写项目的一些总结 获取Redis服务 @Autowired private RedisCache redisCache; String cap ...

  9. 什么是前后端分离 前后端不分离

    前后端不分离 前端页面看到的效果都是由后端控制,由后端渲染页面或重定向到其他页面,后端需要控制前端的展示,前后端耦合度很高. 这种应用模式比较适合纯网页应用,但是当后端对接APP时,APP可能并不需要 ...

最新文章

  1. mysql联合查询数量不一致_Mybatis关联查询,查询出的记录数量与数据库直接查询不一致,如何解决?...
  2. 计算机网络总结:第二章 应用层
  3. 编译Java程序一共要安装什么_如何编译java程序
  4. virtualbox--在win7设置ubuntu虚拟机网络
  5. Android 性能测试初探(四)
  6. MySQL蜜罐在护网中提取攻击者微信ID
  7. 如何根据项目进行PLC选型
  8. Hive教程(01)- 初识Hive
  9. 同步时钟与异步时钟介绍
  10. 给电脑装一个双系统Linux,安装Linux让你的电脑变成双系统的七个理由
  11. 微软苏州STCA面试
  12. Android系统 GPIO状态查询
  13. Maven入门教程(十七)-Maven多Moudle项目创建
  14. 2004年南京美食地图 [转载]
  15. 台式计算机功率图片,【图片】台式机电源别随便买!教你如何选择合适功率的电脑电源!_电脑吧_百度贴吧...
  16. 实现TextView尾部追加可点击的Icon和文本
  17. 微信小程序:紫色特别舒服的UI趣味测试微信小程序
  18. DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)
  19. DY-Tiva-PB 资料 电路图
  20. 【软考系统架构设计师】2021年下半年系统架构设计师考后心得

热门文章

  1. AI技术说:人工智能相关概念与发展简史
  2. 利用C#开发基于snmpsharpnet基础的SNMP开发应用
  3. python环境搭建-pycharm2016软件注册码
  4. iOS多线程编程之锁的理解
  5. JavaScript数值类型及变量
  6. “约定优于配置”与Magento改造尝试四之block、helper和model载入
  7. 贪心算法求解问题的选择准则
  8. 给Lisp程序员的Python简介
  9. 有感于“用界面线程去更新界面元素”
  10. C#中的表达式与运算符