Sharding-JDBC:查询量大如何优化?
主人公小王入职了一家刚起步的创业公司,公司正在研发一款App。为了快速开发出能够投入市场进行宣传的版本,小王可是天天加班到很晚,忙了一段时间后终于把第一个版本赶出来了。
初期功能不多,表也不多,用的MySql存储业务数据。就一个节点,当然每天凌晨有定时备份机制。
下图是目前的一个现状:

得益于运营人员的大力推广,这款App初见成效。注册用户越来越多,查询量越来越大,对于不太会更新的数据小王加上了缓存,又撑了一段时间。
对于某些数据还是要查数据库,按目前的业务发展,单节点的数据库已经快满足不了需求了。而且读和写都在一起,小王打算进行一次优化,将数据库做读写分离,一主多从。
下图是改进后的一个现状:

将读请求全部走从节点,主节点只写入来缓解数据的查询压力,数据库部署这块正好小王公司有个运维可以搞定,但是应用程序这块也得支持多数据源才行呀。
小王是个雷厉风行的人,行动力极强,马上脑袋中就有了方案,配置多个数据源不就行了,然后用不同的数据源进行数据操作就可以了嘛!
伪代码如下:
// 主数据源
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
//指定数据源配置前缀
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
// 从数据源
@Bean(name = "secondaryDataSource")
@Qualifier("secondaryDataSource")
@Primary //在同样的DataSource中,首先使用被标注的DataSource
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
假设我们用JdbcTemplate操作数据库:
@Bean(name = "primaryJdbcTemplate")
public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name = "secondaryJdbcTemplate")
public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
配置完成后我们在操作数据的时候选用不同的JdbcTemplate就可以满足需求了。有个问题是一旦从节点多了起来,也就意味着会有多个JdbcTemplate,使用的时候是不是还得有个算法,用哪个来操作,比较麻烦。
于是小王找到了我,我这人是个热心肠。既然找到了我肯定得帮助下,当然我不是帮小王写代码,只是给他提供思路+方案。
我对小王说:ShardingSphere知道么,你用这个吧,比你自己去配多数据源简单多了。ShardingSphere是后来规划的,最开始是只有 Sharding-JDBC 一款产品,基于客户端形式的分库分表。后面发展变成了现在的Apache ShardingSphere(Incubator) ,它是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(规划中)这3款相互独立,却又能够混合部署配合使用的产品组成。它们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。
经过我的指导小王还是顺利的用Sharding-JDBC将读写分离整出来了,下面给大家分享下步骤。
第一步:创建2个数据库,模拟一主一从,当然如果你有现成的主从环境更好啦
CREATE DATABASE `ds_0` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE DATABASE `ds_1` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `user`(
id bigint(64) not null,
city varchar(20) not null,
name varchar(20) not null,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在ds_0和ds_1这两个库中分别创建一个user表,用于数据操作演示。
第二步:创建一个Maven项目,增加需要的依赖,下面只贴出Sharding-JDBC的,其余的后面我会给出源码地址给大家参考:
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
第三步:配置读写分离的数据源
# 数据源名称集合,对应下面数据源配置的名称
spring.shardingsphere.datasource.names=master,slave
# 主数据源
spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.url=jdbc:mysql://localhost:3306/ds_0?characterEncoding=utf-8
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=123456
# 从数据源
spring.shardingsphere.datasource.slave.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave.url=jdbc:mysql://localhost:3306/ds_1?characterEncoding=utf-8
spring.shardingsphere.datasource.slave.username=root
spring.shardingsphere.datasource.slave.password=123456
# 读写分离配置
spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
# 最终的数据源名称
spring.shardingsphere.masterslave.name=dataSource
# 主库数据源名称
spring.shardingsphere.masterslave.master-data-source-name=master
# 从库数据源名称列表,多个逗号分隔
spring.shardingsphere.masterslave.slave-data-source-names=slave
load-balance-algorithm-type用于配置从库负载均衡算法类型,可选值:ROUND_ROBIN(轮询),RANDOM(随机)
配置完成后可以自行插入数据进行查询和插入的测试,对于应用层使用什么ORM框架无任何影响,你可以用我们前面讲的JdbcTemplate,也可以用Mybatis
等
测试步骤我就不写出来了,比较简单,当然我这边也提供了测试代码,仅供参考:
https://github.com/yinjihuan/sharding-jdbc/tree/master/sjdbc-read-write-springboot
觉得不错的记得给我个Star哦!
还有个问题在读写分离架构中经常出现,那就是读延迟的问题如何解决?
刚插入一条数据,然后马上就要去读取,这个时候有可能会读取不到?
归根到底是因为主节点写入完之后数据是要复制给从节点的,读不到的原因是复制的时间比较长,也就是说数据还没复制到从节点,你就已经去从节点读取了,肯定读不到。
mysql5.7 的主从复制是多线程了,意味着速度会变快,但是不一定能保证百分百马上读取到,这个问题我们可以有两种方式解决:
- 业务层面妥协,是否操作完之后马上要进行读取
- 对于操作完马上要读出来的,且业务上不能妥协的,我们可以对于这类的读取直接走主库,当然Sharding-JDBC也是考虑到这个问题的存在,所以给我们提供了一个功能,可以让用户在使用的时候指定要不要走主库进行读取
在读取前使用下面的方式进行设置就可以了:
public List<User> list() {
// 强制路由主库
HintManager.getInstance().setMasterRouteOnly();
return userRepository.list();
}

Sharding-JDBC:查询量大如何优化?的更多相关文章
- MySQL大表优化方案 Mysql的row_format(fixed与dynamic)
转自:https://mp.weixin.qq.com/s/VY69wWlrVLjRtKU7ULrYGw 当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除 ...
- 优秀后端架构师必会知识:史上最全MySQL大表优化方案总结
本文原作者“ manong”,原创发表于segmentfault,原文链接:segmentfault.com/a/1190000006158186 1.引言 MySQL作为开源技术的代表作之一,是 ...
- MySQL 大表优化方案(长文)
当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.部署.运维的各种复杂度,一般以整型 ...
- Sharding jdbc 强制路由策略(HintShardingStrategy)使用记录
背景 随着项目运行时间逐渐增加,数据库中的数据也越来越多,虽然加索引,优化查询,但是数据量太大,还是会影响查询效率,也给数据库增加了负载. 再加上冷数据基本不使用的场景,决定采用分表来处理数据,从而来 ...
- 记录因Sharding Jdbc批量操作引发的一次fullGC
周五晚上告警群突然收到了一条告警消息,点开一看,应用 fullGC 了. 于是赶紧联系运维下载堆内存快照,进行分析. 内存分析 使用 MemoryAnalyzer 打开堆文件 mat 下载地址:htt ...
- MySQL 千万级 数据库或大表优化
首先考虑如下因素: 1.数据的容量:1-3年内会大概多少条数据,每条数据大概多少字节: 2.数据项:是否有大字段,那些字段的值是否经常被更新: 3.数据查询SQL条件:哪些数据项的列名称经常出现在WH ...
- Spring boot项目集成Sharding Jdbc
环境 jdk:1.8 framework: spring boot, sharding jdbc database: MySQL 搭建步骤 在pom 中加入sharding 依赖 <depend ...
- jdbc mysql crud dao模型 sql注入漏洞 jdbc 操作大文件
day17总结 今日内容 l JDBC 1.1 上次课内容总结 SQL语句: 1.外键约束:foreign key * 维护多个表关系! * 用来保证数据完整性! 2.三种关系: * 一对多: * 一 ...
- JDBC性能分析与优化
JDBC性能分析与优化V1.0http://www.docin.com/p-758600080.html
随机推荐
- Python连载48-正则表达式(中)
一.正则的写法: . (点好) :表示任意一个字符,除了\n,比如查找所有的一个字符\. [] :匹配中括号中列举的任意字符,比如[L,Y,0], LLY, Y0, LIU \d :任意一个数字 \D ...
- dva+umi+antd项目从搭建到使用(没有剖验证,不知道在说i什么)
先创建一个新项目,具体步骤请参考https://www.cnblogs.com/darkbluelove/p/11338309.html 一.添加document.ejs文件(参考文档:https:/ ...
- 【2016NOI十连赛2-2】黑暗
[2016NOI十连赛2-2]黑暗 题目大意:定义一个无向图的权值为连通块个数的\(m\)次方.求\(n\)个点的所有无向图的权值和.多次询问. 数据范围:\(T\leq 1000,n\leq 300 ...
- 扎心一问!你凭什么成为top1%的Java工程师?
目录 1.解决生产环境里的突发故障 2.对棘手的线上性能问题进行优化 3.锻造区别于普通码农的核心竞争力 4.打磨架构设计能力 5.你凭什么成为 top1%? 你工作几年了? 是否天天CRUD到吐 ...
- SQLServer临时库文件太大,迁移tempdb数据库
问题描述: 最近公司这边tempdb库文件很大,几百GB的节奏 不过安装数据库的时候,tempdb最好不要放在C盘是放在D盘其他数据盘的 如果没有放在其他盘符下面,就需要做迁移了 解决方法: 如果te ...
- Java实现编辑距离算法
Java实现编辑距离算法 编辑距离,又称Levenshtein距离(莱文斯坦距离也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数,如果它们的距离越大,说明它 ...
- 2019_JAVA面试题_真实总结
来自刚被某互联网公司录取的朋友的分享. 整理的面试题1: 1.Java里面有哪几种基础数据类型, 2.Char为何是两个字节, 3.Object有哪些方法 4.final修饰变量,函数,类的作用, 5 ...
- [04]ASP.NET Core Web 项目文件
ASP.NET Core Web 项目文件 本文作者:梁桐铭- 微软最有价值专家(Microsoft MVP) 文章会随着版本进行更新,关注我获取最新版本 本文出自<从零开始学 ASP.NET ...
- Fusionstorage的逻辑架构
Fusionstorage Fusionstorage的逻辑架构 Mdc:元数据控制,实现对分布式集群的状态控制,以及控制数据分布式规则,数据重建规则等,mdc默认部署在3个节点的zk盘上,形成mdc ...
- oracle学习笔记(十三) 查询练习(三) 子查询查询
子查询练习 create table empployee_demo( empno number(4) not null primary key, --员工编号,主键 ename varchar2(10 ...