【源码解析】Sharding-Jdbc中的算法
Sharding-jdbc中的很多地方涉及到算法,比如主从配置这块、分库分表这块。本文主要从源码角度介绍下,目前主要包含哪些算法,以及这些算法的内容。
一、读写分离(主从配置)
这块的代码主要在core模块中的api/algorithm/masterslave下面,这块的算法的主要目的,其实是在读的时候,如何选择从数据库。按照常规的理解,可以有以下几种(参考dubbo):
- 随机算法
- 轮询
- 最小活跃
- 一致性hash
目前在sharding-jdbc中,实现了前两种,我们看下是如何实现的。
首先是一个接口,定义了获取slave的方法,即:
public interface MasterSlaveLoadBalanceAlgorithm {
/**
* Get data source.
*
* @param name master-slave logic data source name
* @param masterDataSourceName name of master data sources
* @param slaveDataSourceNames names of slave data sources
* @return name of selected data source
*/
String getDataSource(String name, String masterDataSourceName, List<String> slaveDataSourceNames);
}
最终需要返回的是slave的名称,后续根据这个名称可以获取到连接池。
下面我们看下两种实现:
- RandomMasterSlaveLoadBalanceAlgorithm
public String getDataSource(final String name, final String masterDataSourceName, final List<String> slaveDataSourceNames) {
return slaveDataSourceNames.get(new Random().nextInt(slaveDataSourceNames.size()));
}
可以看到,随机了一个slave集群大小的随机数,然后从slave list中获取对应的slave name。
- RoundRobinMasterSlaveLoadBalanceAlgorithm
private static final ConcurrentHashMap<String, AtomicInteger> COUNT_MAP = new ConcurrentHashMap<>();
@Override
public String getDataSource(final String name, final String masterDataSourceName, final List<String> 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());
}
这块用了一个缓存,COUNT_MAP,缓存的内容是name-count的键值对,而count是一个原子类,它的值一直是0,1,...,slaves.size()-1,0,1..这样循环,所以每个slave都会被轮询到。
二、分库分表
分库分表的算法目前支持的内容包括:
- 精确分库分表PreciseShardingValue
- 按照范围分库分表RangeShardingValue
- 按照列表分库分表ListShardingValue
这块主要是定义了一些接口,具体的实现还是要看自己来实现。我们来看下example中的一些已经实现的算法。
public final class PreciseModuloDatabaseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
@Override
public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Integer> shardingValue) {
for (String each : availableTargetNames) {
if (each.endsWith(shardingValue.getValue() % 2 + "")) {
return each;
}
}
throw new UnsupportedOperationException();
}
}
这块就是实现了一个精准分片的算法,我们主要看下doSharding这个方法,里面包含两个参数availableTargetNames和shardingValue。那么这两个是什么呢?我们debug一下,跟踪一下代码,可以看到,shardingValue其实就是分片项,也就是比如order_id、user_id等等字段值,而availableTargetNames就是所谓的实际数据库表节点。这边遍历的也是实际节点,当分片项(或分片字段)满足一定的条件时,返回实际数据库表节点,用于组装sql。
总的来说,分片算法这块其实根据自己的业务需求自己进行扩展的,总的来说还是要根据实际的机器部署情况来。另外读写分离这块是否需要进行扩展,也是看后续的需要。
【源码解析】Sharding-Jdbc中的算法的更多相关文章
- Spring5源码解析-Spring框架中的单例和原型bean
Spring5源码解析-Spring框架中的单例和原型bean 最近一直有问我单例和原型bean的一些原理性问题,这里就开一篇来说说的 通过Spring中的依赖注入极大方便了我们的开发.在xml通过& ...
- Mybatis源码解析1—— JDBC
在之前的文章中,我为大家介绍了 Mybatis 的详细用法,算是基础教程. 详细链接:Mybatis 基础教程 言归正传,只懂基础可不行,接下来将给大家带来高阶的源码解析教程,从浅入深,通过源码解析, ...
- 从源码解析 Spring JDBC 异常抽象
初入学习 JDBC 操作数据库,想必大家都写过下面的代码: 数据库为:H2 如果需要处理特定 SQL 异常,比如 SQL 语句错误,这个时候我们应该怎么办? 查看 SQLException 源码,我们 ...
- Redis源码解析:13Redis中的事件驱动机制
Redis中,处理网络IO时,采用的是事件驱动机制.但它没有使用libevent或者libev这样的库,而是自己实现了一个非常简单明了的事件驱动库ae_event,主要代码仅仅400行左右. 没有选择 ...
- html 网页源码解析:bs4中BeautifulSoup
from bs4 import BeautifulSoup result=requests.request("get","http://www.baidu.com&quo ...
- ReactiveCocoa源码解析(四) Signal中的静态属性静态方法以及面向协议扩展
上篇博客我们聊了Signal的几种状态.Signal与Observer的关联方式以及Signal是如何向关联的Observer发送事件的.本篇博客继续上篇博客的内容,来聊一下Signal类中静态的ne ...
- ReactiveSwift源码解析(四) Signal中的静态属性静态方法以及面向协议扩展
上篇博客我们聊了Signal的几种状态.Signal与Observer的关联方式以及Signal是如何向关联的Observer发送事件的.本篇博客继续上篇博客的内容,来聊一下Signal类中静态的ne ...
- 【Mybatis源码解析】- JDBC连接数据库的原理和操作
JDBC连接数据库的原理和操作 JDBC即Java DataBase Connectivity,java数据库连接:JDBC 提供的API可以让JAVA通过API方式访问关系型数据库,执行SQL语句, ...
- Syncthing源码解析 - 在Gogland中对Syncthing的各个模块进行调试?
Syncthing的模块很多,各自负责不同的功能,如何能够对各个模块进行调试?Syncthing开发者早就想到这个问题了,允许开发者对任意模块进行单独调试,也允许同时对所有模块调试,调试方式是打印各个 ...
随机推荐
- Kettle文本文件输出和输入控件使用中,换行符导致的问题处理
1.如下图通过输入控件从数据库读取数据然后生成TXT文本文件,TXT文件生成原则是每一条数据生成一行数据,第二条数据换行保存 2.如下图所示,使用文本文件输入控件读入上图生成的文件,文件读入原则是按行 ...
- wpf 中英文版编写
var uriC = new Uri("/YTManage.Language;component/Chinese.xaml", UriKind.Relative); // 得到资源 ...
- java类加载小记
java类只有当创建实体或被调用时才会加载,加载时按 编码顺序 先加载static后加载普通的.static模块和static变量都是同一等级的,谁写前面就先加载谁. 在调用某个静态类的方法时,会按编 ...
- DevOps之服务手册
唠叨话 关于德语噢屁事的知识点,仅提供精华汇总,具体知识点细节,参考教程网址,如需帮助,请留言. <DevOps服务手册(Manual)> <IT资源目标化>1.设施和设备(I ...
- Fatal error in launcher:Unable to create process using '"'
Windows下同时存在Python2和Python3使用pip时系统报错:Fatal error in launcher: Unable to create process using '" ...
- 典型的NIO代码
public void selector() throws IOException { ByteBuffer buffer = ByteBuffer.allocate(1024); Selector ...
- JS中处理单个反斜杠(即转义字符的处理)
问题来源:在表单的<input>标签中对输入的字符串进行大写转换.一不小心输入了反斜杠 \ 如下图所示: 输入 chn\ 的时候,在 IE8 下弹出一个js错误.(在实际的项目的表单 ...
- MongoDB基本命令行操作
1. 连接MongoDB: Mongodb://username:password@hostname/dbname 2. 创建数据库: use dbname:如果数据库不存在则创建数据库,否则切换到指 ...
- eclipse项目中引入shiro-freemarker-tags会jar包冲突
maven项目中引入了这个依赖. <dependency> <groupId>net.mingsoft</groupId> <artifactId>sh ...
- ES6中函数新增的方式方法
---恢复内容开始--- 绪 言 ES6 大家对JavaScript中的函数都不陌生.今天我就为大家带来ES6中关于函数的一些扩展方式和方法. 1.1函数形参的默认值 1.1.1基本用法 ES6 ...