需求

  1. 一主两从,做读写分离。
  2. 多个从库之间实现负载均衡。
  3. 可手动强制部分读请求到主库上。(因为主从同步有延迟,对实时性要求高的系统,可以将部分读请求也走主库)

本次不讨论 MySQL如何配置主从同步相关问题

库表SQL

-- 主库
CREATE DATABASE `master`; CREATE TABLE `t_order` (
`order_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`business_id` int(4) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `t_order` VALUES (1,1,112); -- 从库1
CREATE DATABASE `slave1` ;
CREATE TABLE `t_order` (
`order_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`business_id` int(4) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ; INSERT INTO `t_order` VALUES (2,2,112); -- 从库2
CREATE DATABASE `slave2` ;
CREATE TABLE `t_order` (
`order_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`business_id` int(4) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `t_order` VALUES (3,3,112);

pom.xml

<!-- https://mvnrepository.com/artifact/io.shardingjdbc/sharding-jdbc-core -->
<dependency>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>2.0.0.M2</version>
</dependency>
<dependency>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
<version>2.0.0.M2</version>
</dependency>

spring配置文件

<bean id="master" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${jdbc.url.master}"></property>
<property name="username" value="${jdbc.username.master}"></property>
<property name="password" value="${jdbc.password.master}"></property>
<property name="maxActive" value="100"/>
<property name="initialSize" value="10"/>
<property name="maxWait" value="60000"/>
<property name="minIdle" value="5"/>
</bean> <bean id="slave1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${jdbc.url.slave1}"></property>
<property name="username" value="${jdbc.username.slave1}"></property>
<property name="password" value="${jdbc.password.slave1}"></property>
<property name="maxActive" value="100"/>
<property name="initialSize" value="10"/>
<property name="maxWait" value="60000"/>
<property name="minIdle" value="5"/>
</bean> <bean id="slave2" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${jdbc.url.slave2}"></property>
<property name="username" value="${jdbc.username.slave2}"></property>
<property name="password" value="${jdbc.password.slave2}"></property>
<property name="maxActive" value="100"/>
<property name="initialSize" value="10"/>
<property name="maxWait" value="60000"/>
<property name="minIdle" value="5"/>
</bean> <bean id="randomStrategy" class="io.shardingjdbc.core.api.algorithm.masterslave.RandomMasterSlaveLoadBalanceAlgorithm" /> <master-slave:data-source id="shardingDataSource" master-data-source-name="master" slave-data-source-names="slave1,slave2" strategy-ref="randomStrategy" />

单测

写:

    @Test
public void insert() throws Exception { Order record = new Order();
record.setBusinessId(112);
record.setUserId(111);
record.setOrderId(12212121); int result = orderMapper.insertSelective(record) ; System.out.println( result > 0 ? "插入成功" : "插入失败");
}

运行结果:

查:

slave1 只有1条数据,主键order_id = 2 ; slave2 也只有1条数据,主键order_id = 3 。所以,如果查询到的结果orderId等于1就说明读请求进入到slave1,同理,如果查询出来的orderId等于0 就说明读请求进入到slave2。

 public void selectByExample3() throws Exception {

        final int[] slave1 = {0};
final int[] slave2 = {0}; for (int i = 0; i < 100; i++) {
((Runnable) () -> {
OrderExample example = new OrderExample();
example.createCriteria().andBusinessIdEqualTo(112); List<Order> orderList = orderMapper.selectByExample(example); if (orderList.get(0).getOrderId() == 2) {
System.out.printf("读到slave1 读到的数据是{}", JSONObject.toJSONString(orderList.get(0)));
slave1[0]++;
} else if (orderList.get(0).getOrderId() == 3) {
System.out.printf("读到slave2 读到的数据是{}", JSONObject.toJSONString(orderList.get(0)));
slave2[0]++;
}
System.out.println(JSONObject.toJSONString(orderList));
}).run();
} System.out.println("+++++++++++++++++++++++++++++++++++++++");
System.out.println("+++++++++++++++++++++++++++++++++++++++");
System.out.println("slave1读到的次数-->" + slave1[0]);
System.out.println("slave2读到的次数-->" + slave2[0]);
System.out.println("+++++++++++++++++++++++++++++++++++++++");
System.out.println("+++++++++++++++++++++++++++++++++++++++");
}

运行截图:

强制路由

通常做读写分离,都会遇到的一个问题就是主从同步延迟。有时,为了简单解决主从同步问题,我们会想强制部分读请求到主库上,而非从库上。

HintManager 分片键值管理器

官方文档的解释:

基于暗示(Hint)的分片键值管理器

但是对于读写分离这种形式的强制路由 , 其实官方文档说的几个方法都不适用. 我们可使用hintManager.setMasterRouteOnly() .

单测

@Test
public void HintManagerTest() { HintManager hintManager = HintManager.getInstance() ; hintManager.setMasterRouteOnly(); OrderExample example = new OrderExample();
example.createCriteria().andBusinessIdEqualTo(112); List<Order> orderList = orderMapper.selectByExample(example); System.out.println(JSONObject.toJSONString(orderList)); hintManager.close(); }

sharding-JDBC 实现读写分离的更多相关文章

  1. Sharding+SpringBoot+Mybatis 读写分离

    基于Sharding JDBC的读写分离 1.引入pom.xml <dependencies> <!-- mybatis --> <dependency> < ...

  2. java环境下的数据库读写分离

    方案很多:阿里的中间件cobar.aop注解方式.com.mysql.jdbc.ReplicationDriver读写分离驱动MySQL数据库的同步. MySQL是开源的关系型数据库系统.主从同步复制 ...

  3. MySQL中间件之ProxySQL(10):读写分离方法论

    返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.html 1.不同类型的读写分离 数据库中间件最基本的功能就是实现读写分离,Pr ...

  4. ProxySQL(10):读写分离方法论

    文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9318558.html 不同类型的读写分离 数据库中间件最基本的功能就是实现读写分离,ProxySQL当然也支 ...

  5. sharding sphere 分表分库 读写分离

    sharding jdbc: sharding sphere 的 一部分,可以做到 分表分库,读写分离. 和 mycat 不同的 是 sharding jdbc 是 一个 jdbc 驱动 在 驱动这个 ...

  6. sharding demo 读写分离 U (分库分表 & 不分库只分表)

    application-sharding.yml sharding: jdbc: datasource: names: ds0,ds1,dsx,dsy ds0: type: com.zaxxer.hi ...

  7. DB层面上的设计 分库分表 读写分离 集群化 负载均衡

    第1章  引言 随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题.对于一个大型的 互联网应用,每天几十亿的PV无疑对数据库造成了相当高的负载.对于系统的稳定性和扩展性造成了极大的 ...

  8. DBA 小记 — 分库分表、主从、读写分离

    前言 我在上篇博客 "Spring Boot 的实践与思考" 中比对不同规范的 ORM 框架应用场景的时候提到过主从与读写分离,本篇随笔将针对此和分库分表进行更深入地探讨. 1. ...

  9. spring boot sharding-jdbc实现分佈式读写分离和分库分表的实现

    分布式读写分离和分库分表采用sharding-jdbc实现. sharding-jdbc是当当网推出的一款读写分离实现插件,其他的还有mycat,或者纯粹的Aop代码控制实现. 接下面用spring ...

  10. SpringBoot使用Sharding-JDBC读写分离

    本文介绍SpringBoot使用当当Sharding-JDBC进行读写分离. 1.有关Sharding-JDBC 本文还是基于当当网Sharding-Jdbc的依赖,与上一篇使用Sharding-Jd ...

随机推荐

  1. javascript push 和 concat 的区别

    array.push(item1,item2,item3...) array.concat(item1,item2,item3...) 1. push和concat的元素都既可以是普通元素(任意类型) ...

  2. selenium测试-open chrome

    通过selenium来打开浏览器测试之前,需要确认本地已安装相应的webdriver,本例以chrome为例. 1. 查看本地chrome版本,以此确认需要安装的webdriver版本 查看chrom ...

  3. Jokewithpermutation (DFS)

    Problem J. Jokewithpermutation Input file: joke.inOutput file: joke.out Joey had saved a permutation ...

  4. rn初体验

    react-native 需要的工具 .nodejs .rn cli .xcode and as ---------------- 打开终端,切换到根路径(mac中修改npm的默认安装来源) 一.op ...

  5. 如何写出高性能DOM?

    为什么要写高性能DOM? 一个网站,在页面上承载最多内容的就是DOM,而且无论是我们通过加载JS.加载图片,他们也是通过写HTML标签来实现的.而我们性能优化要做的无非就是几大块: 站点的网络消耗 D ...

  6. mysql 添加字段 修改字段为not null

    添加一个字段 ALTER TABLE jw_user_role ADD zk_env VARCHAR(16); 修改字段为not null,还要把原来的类型也写出来 ALTER TABLE jw_us ...

  7. 动态规划:区间DP与环形DP

    区间型动态规划的典型例题是石子归并,同时使用记忆化搜索实现区间动归是一种比较容易实现的方式,避免了循环数组实现的时候一些边界的判断 n堆石子排列成一条线,我们可以将相邻的两堆石子进行合并,合并之后需要 ...

  8. web版canvas做飞机大战游戏 总结

    唠唠:两天的时间跟着做了个飞机大战的游戏,感觉做游戏挺好的.说是用html5做,发现全都是js.说js里一切皆为对象,写的最多的还是函数,都是函数调用.对这两天的代码做个总结,希望路过的大神指点一下, ...

  9. 【poj1830-开关问题】高斯消元求解异或方程组

    第一道高斯消元题目~ 题目:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关 ...

  10. 【BZOJ】1529 [POI2005]ska Piggy banks

    [算法](强连通分量)并查集 [题解] 1.用tarjan计算强连通分量并缩点,在新图中找入度为0的点的个数就是答案. 但是,会爆内存(题目内存限制64MB). 2.用并查集,最后从1到n统计fa[i ...