首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

16.sjdbc之读写分离

读写分离支持范围

提供了一主多从的读写分离配置,可独立使用,也可配合分库分表使用。

同一线程且同一数据库连接内,如有写入操作,以后的读操作均从主库读取,用于保证数据一致性。

Spring命名空间。

基于Hint的强制主库路由。

读写分离不支持范围

主库和从库的数据同步

主库和从库的数据同步延迟导致的数据不一致。

主库双写或多写。

读写分离支持项和不支持范围摘自sharding-jdbc使用指南?读写分离:http://shardingjdbc.io/docs_1.x/02-guide/master-slave/

简单总结

sharding-jdbc的读写分离不甘于数据库层面的东西。比如主从同步,依赖mysql本身的同步机制,而不是由sharding-jdbc去支持。而主从同步延迟这种问题,sharding-jdbc也没必要去解决。

源码分析

MasterSlave or Sharding

选择MasterSlaveDataSource还是普通的ShardingDataSource逻辑非常简单,就看根据sharding配置能否得到slave,核心源码如下:

强制主&负载均衡选择

主从数据源中根据负载均衡策略获取数据源核心源码--MasterSlaveDataSource.java:

主路由逻辑如下:

非查询SQL(SQLType.DQL != sqlType)

当前数据源在当前线程访问过主库(数据源访问过主库就会通过ThreadLocal将DML_FLAG置为true,从而路由主库)(DML_FLAG.get())

HintManagerHolder方式设置了主路由规则(HintManagerHolder.isMasterRouteOnly())

当前线程访问过主库后,后面的操作全部切主,是为了防止主从同步数据延迟导致写操作后,读不到最新的数据?我想应该是这样的^^

主从负载均衡分析

从对的分析可知,如果不符合强制主路由规则,那么会根据负载均衡策略选多个slave中选取一个slave,MasterSlaveLoadBalanceAlgorithm接口有两个实现类:

RoundRobinMasterSlaveLoadBalanceAlgorithm即轮训策略;

RandomMasterSlaveLoadBalanceAlgorithm随机策略;

笔者有话要说:这里没有出镜率比较高的一致性hash策略,这倒是个意外,哈!

轮询策略

轮询方式的实现类为RoundRobinMasterSlaveLoadBalanceStrategy,核心源码如下:

注意轮询选择最后一行代码:

count.getAndIncrement()然后取模,而count的初始值为0。这就有一个非常小的隐患,当轮询策略选择了Integer.MAX_VALUE次后,再count.getAndIncrement()就会变成负数,从而导致执行List集合的get()方法出错。验证这个潜在问题的代码如下:

模拟主从总计3个节点,当轮询Integer.MAX_VALUE-3后,再尝试轮询5次,在第4次就会报错!

笔者在github上找到了sharding-sphere最新的代码,这个问题依然存在,明天找张亮大神确认一下,最新源码路径为:

https://github.com/sharding-sphere/sharding-sphere/blob/dev/sharding-core/src/main/java/io/shardingsphere/core/api/algorithm/masterslave/RoundRobinMasterSlaveLoadBalanceAlgorithm.java

随机策略

随机方式的实现类为RandomMasterSlaveLoadBalanceAlgorithm,核心源码如下:

默认策略

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180915G0A3D300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com