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中的算法的更多相关文章

  1. Spring5源码解析-Spring框架中的单例和原型bean

    Spring5源码解析-Spring框架中的单例和原型bean 最近一直有问我单例和原型bean的一些原理性问题,这里就开一篇来说说的 通过Spring中的依赖注入极大方便了我们的开发.在xml通过& ...

  2. Mybatis源码解析1—— JDBC

    在之前的文章中,我为大家介绍了 Mybatis 的详细用法,算是基础教程. 详细链接:Mybatis 基础教程 言归正传,只懂基础可不行,接下来将给大家带来高阶的源码解析教程,从浅入深,通过源码解析, ...

  3. 从源码解析 Spring JDBC 异常抽象

    初入学习 JDBC 操作数据库,想必大家都写过下面的代码: 数据库为:H2 如果需要处理特定 SQL 异常,比如 SQL 语句错误,这个时候我们应该怎么办? 查看 SQLException 源码,我们 ...

  4. Redis源码解析:13Redis中的事件驱动机制

    Redis中,处理网络IO时,采用的是事件驱动机制.但它没有使用libevent或者libev这样的库,而是自己实现了一个非常简单明了的事件驱动库ae_event,主要代码仅仅400行左右. 没有选择 ...

  5. html 网页源码解析:bs4中BeautifulSoup

    from bs4 import BeautifulSoup result=requests.request("get","http://www.baidu.com&quo ...

  6. ReactiveCocoa源码解析(四) Signal中的静态属性静态方法以及面向协议扩展

    上篇博客我们聊了Signal的几种状态.Signal与Observer的关联方式以及Signal是如何向关联的Observer发送事件的.本篇博客继续上篇博客的内容,来聊一下Signal类中静态的ne ...

  7. ReactiveSwift源码解析(四) Signal中的静态属性静态方法以及面向协议扩展

    上篇博客我们聊了Signal的几种状态.Signal与Observer的关联方式以及Signal是如何向关联的Observer发送事件的.本篇博客继续上篇博客的内容,来聊一下Signal类中静态的ne ...

  8. 【Mybatis源码解析】- JDBC连接数据库的原理和操作

    JDBC连接数据库的原理和操作 JDBC即Java DataBase Connectivity,java数据库连接:JDBC 提供的API可以让JAVA通过API方式访问关系型数据库,执行SQL语句, ...

  9. Syncthing源码解析 - 在Gogland中对Syncthing的各个模块进行调试?

    Syncthing的模块很多,各自负责不同的功能,如何能够对各个模块进行调试?Syncthing开发者早就想到这个问题了,允许开发者对任意模块进行单独调试,也允许同时对所有模块调试,调试方式是打印各个 ...

随机推荐

  1. C#综合揭秘——细说多线程(二)

    /* 异步写入 FileStream中包含BeginWrite.EndWrite 方法可以启动I/O线程进行异步写入. public override IAsyncResult BeginWrite ...

  2. 提取多层嵌套Json数据

    在.net 2.0中提取这样的json {"name":"lily","age":23,"addr":{"ci ...

  3. 使用OLAMISDK实现一个语音输入数字进行24点计算的iOS程序

    前言 在目前的软件应用中,输入方式还是以文字输入方式为主,但是语音输入的方式目前应用的越来越广泛.这是一个利用 Olami SDK 编写的一个24点iOS程序,是通过语音进行输入. Olami SDK ...

  4. 最佳时间买入卖出股票 Best Time to Buy and Sell Stock LeetCode

    LeetCode 我们有一个股票的数组,数组是每时间的钱,我们只能买入一次和卖出一次,求我们的最大收益. 我们知道了一个数组,那么我们可以在低价买入,然后高价卖出,但是需要知道我们的低价需要在高价之前 ...

  5. http服务详解(2)——httpd2.2的配置文件常见设置

    摘要:一个服务的配置文件非常重要,弄懂配置文件是熟练掌握服务的必要前提. 一.httpd-2.2常见文件介绍 (1)配置文件: 主配置文件尽量别改,改自己的子配置文件 /etc/httpd/conf/ ...

  6. 从狗日的Oracle上下载jdk

    就算因为需要我要用到java,我依然要说java是最垃圾的语言,现在oracle又让我明白什么叫最垃圾的公司. 从oracle下载文件要求你同意他的协议,但是你会发现很多时候就算你点了同意依然不可以下 ...

  7. 我们的代码为什么要压缩成7z?

    代码为什么要压缩成7z? a. 代码的复制速度是非常慢的.  几M或几KB都是常事. b. 压缩成7z格式后,压缩速度迅速提高上百倍 网页为什么要压缩成7z? 怎么使用7z压缩(以好压2345为例子) ...

  8. MySQL复制之理论篇

    一.MySQL复制概述 MySQL支持两种复制方式:基于行的复制和基于语句的复制(逻辑复制).这两种方式都是通过在主库上记录 二进制日志.在备库重放日志的方式来实现异步的数据复制,其工作原理如下图: ...

  9. macOs升级到10.13.1Beta || JAVA升级到最新版之后PhpStorm菜单栏问题

    macOs升级到10.13.1Beta || JAVA升级到最新版之后PhpStorm菜单栏会消失,估计不止出现在PhpStorm,一系列jetbrains的产品可能都会有这个问题,包括eclipis ...

  10. RobotFrameWork安装笔记

    1.   RobotFrameWork安装配置笔记 1.1. 安装环境 64位win10家庭中文版 网上很多这方面的教程,但是比较零散,这里是自己安装配置的一个简单的笔记. 1.2. 安装说明 由于R ...