前言

又是一个夜黑风高的晚上,带上无线耳机听一曲。突然很感慨一句话:生活就像心电图,一帆风顺就证明你挂了。 就如同我们干运维的,觉得很简单的事情,有时候能干出无限可能。还是言归正传吧,这一次我们来说说stringhash分区算法。

1.hash分区算法

2.stringhash分区算法

3.enum分区算法

4.numberrange分区算法

5.patternrange分区算法

6.date分区算法

7.jumpstringhash算法

StringHash分区算法的配置

<tableRule name="rule_hashString">
<rule>
<columns>name</columns>
<algorithm>func_hashString</algorithm>
</rule>
</tableRule> <function name="func_hashString" class="StringHash">
<property name="partitionCount">3,2</property>
<property name="partitionLength">3,4</property>
<property name="hashSlice">0:3</property>
</function>

和之前的hash算法一样。需要在rule.xml中配置tableRule和function。

  • tableRule标签,name对应的是规则的名字,而rule标签中的columns则对应的分片字段,这个字段必须和表中的字段一致。algorithm则代表了执行分片函数的名字。
  • function标签,name代表分片算法的名字,算法的名字要和上面的tableRule中的标签相对应。class:指定分片算法实现类。property指定了对应分片算法的参数。不同的算法参数不同。

1.partitionCount:指定分区的区间数,具体为 C1 +C2 + ... + Cn

2.partitionLength:指定各区间长度,具体区间划分为 [0, L1), [L1, 2L1), ..., [(C1-1)L1, C1L1), [C1L1, C1L1+L2), [C1L1+L2, C1L1+2L2), ... 其中,每一个区间对应一个数据节点。

3.hashSlice:指定参与hash值计算的key的子串。字符串从0开始索引计数

接下来我们来详细介绍一下StringHash的工作原理。我们以上面的配置为例。

1.在启动的时候,两个数组点乘做运算,得到取模数。

2.两个数组进行叉乘,得出物理分区表。

3.根据hashSlice二维数组,把分片字段的字符串进行截取。

字符串截取的范围是hashSlice[0]到hashSlice[1]。比如我这里设置0,3。‘buddy'这个字符串就会截取出bud,类似数据库中的substring函数。

4.将截取出来的字符串做hash,这个hash的计算方法我研究了一下dble的源代码。源代码如下:

 /**
* String hash:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] <br>
* h = 31*h + s.charAt(i); => h = (h << 5) - h + s.charAt(i); <br>
*
* @param start hash for s.substring(start, end)
* @param end hash for s.substring(start, end)
*/
public static long hash(String s, int start, int end) {
if (start < 0) {
start = 0;
}
if (end > s.length()) {
end = s.length();
}
long h = 0;
for (int i = start; i < end; ++i) {
h = (h << 5) - h + s.charAt(i);
}
return h;
}

这段源代码的意思其实上面有解释。算法是s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1]。然后接下来它说明h = 31*h + s.charAt(i)是等同于h = (h << 5) - h + s.charAt(i)。大家是不是还是云里雾里的。你可以去看文章结尾关于这一点的详细解释。

这里我们把这个公式分解一下,根据上述的公式,我们能推导出下列算术式:

i=0 -> h = 31 * 0 + s.charAt(0)

i=1 -> h = 31 * (31 * 0 + s.charAt(0)) + s.charAt(1)

i=2 -> h = 31 * (31 * (31 * 0 + s.charAt(0)) + s.charAt(1)) + s.charAt(2)

i=3 -> h = 31 * (31 * (31 * (31 * 0 + s.charAt(0)) + s.charAt(1)) + s.charAt(2)) + s.charAt(3)

.......以此内推

假设我们的字符串是"buddy",我们截取0-3字符串,我们来算一下。根据上面的函数来写段java代码编译运行。

public class test {
public static void main(String args[]) {
String Str = new String("buddy");
System.out.println(hash(Str,0,3));
} public static long hash(String s, int start, int end) {
if (start < 0) {
start = 0;
}
if (end > s.length()) {
end = s.length();
}
long h = 0;
for (int i = start; i < end; ++i) {
h = (h << 5) - h + s.charAt(i);
}
return h;
}
} [root@mysql5 java]# javac test.java
[root@mysql5 java]# java test
97905

通过运行程序截取字符串buddy,0-3得到的结果是97905。那么这个结果是怎么算出来的。首先截取0,3,最终截取的是三个字符串bud。索引从0开始计数对应的就是i=2。根据i=2的公式:

i=2 -> h = 31 * (31 * (31 * 0 + s.charAt(0)) + s.charAt(1)) + s.charAt(2)

我们可以查询ascii表

s.charAt(0),是算"b"这个字母的ASCII值,十进制数字为98

s.charAt(1),是算"u"这个字母的ASCII值,十进制数字为117

s.charAt(1),是算"d"这个字母的ASCII值,十进制数字为100

把上述三个值带入到公式得出 31 * (31 * (31 * 0 + 98) + 117) + 100 = 97905。正好和我们程序计算的值一样。

5.对计算出来的值取模,然后落在指定的分区中。

97905 mod 17 =2 根据取模的值,落在了dn1分区,dn1分区是存放(0,3)的。

6.让我们建表来测试一下,是不是落在第1个分区。



如图所示,当我们执行插入name='buddy',然后再一次查询的name='buddy'的时候,直接路由到了第一个分区。和我们之前计算的结果一致。

注意事项

  1. 该分区算法和hash分区算法有同样的限制(注意事项3除外)
  2. 分区字段为字符串类型

后记

今天介绍的stringhash和hash分区算法大致相同,只不过对于字符串需先计算出hash值。该算法有个经典的数字叫31。这个数字大有来头。《Effective Java》中的一段话说明了为什么要用31,因为31是一个奇质数,如果选择一个偶数的话,乘法溢出信息将丢失。因为乘2等于移位运算。使用质数的优势不太明显,但这是一个传统。31的一个很好的特性是乘法可以用移位和减法来代替以获得更好的性能:31*i==(i<<5)-i。现代的 Java 虚拟机可以自动的完成这个优化。

The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional. A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i. Modern VMs do this sort of optimization automatically.

如果你前面没看懂前面那段java代码,现在应该明白(h << 5) - h的结果其实就等于31*h。

今天到这儿,后续将继续分享其他的算法。谢谢大家支持!

数据库中间件分片算法之stringhash的更多相关文章

  1. 数据库中间件分片算法之enum

    前言 最近挺焦虑的,不知道未来该做什么,方向又是什么.只能用别慌,月亮也正在大海的某处迷茫.来安慰下自己.不过学习的初心咱们还是不要忘记.今天我们学习的是enum分片算法. 1.hash分区算法 2. ...

  2. 开源数据库中间件-MyCat

    开源数据库中间件-MyCat产生的背景 如今随着互联网的发展,数据的量级也是成指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系型数据库已经无法满足快速查询与插入数据的需求.这 ...

  3. 数据库中间件MyCat学习总结(1)——MyCat入门简介

    为什么需要MyCat? 虽然云计算时代,传统数据库存在着先天性的弊端,但是NoSQL数据库又无法将其替代.如果传统数据易于扩展,可切分,就可以避免单机(单库)的性能缺陷. MyCat的目标就是:低成本 ...

  4. 对话DDM:分布式数据库中间件全解析

    进入云计算时代,传统的数据库在性能和容量等方面已无法满足企业的要求,随着数据量的不断骤增,易于扩展.拆分的数据库解决方案对于企业的云化转型更是显得尤为重要.为使企业应用上云更简单,分布式数据库中间件D ...

  5. 数据库中间件DBLE学习(二) 学习配置schema.xml

    前言 一边有一个经常引诱我让我"娱乐至死"的视频,还有一个不停"鞭策"我让我快点学习的大BOSS.正是有这两种极端的爱才让我常常在自信中明白自己努力的方向.嗯, ...

  6. 数据库中间件DBLE学习(一) 基础介绍和快速搭建

    dble基本架构简介 dble是上海爱可生信息技术股份有限公司基于mysql的高可用扩展性的分布式中间件.江湖人送外号MyCat Plus.开源地址 我们首先来看架构图,外部应用通过NIO/AIO进行 ...

  7. Apache ShardingSphere:由开源驱动的分布式数据库中间件生态

    2021 年 7 月 21 日 2021 亚马逊云科技中国峰会现场,SphereEx 联合创始人.Apache ShardingSphere PMC 潘娟受邀参与此次峰会,以<Apache Sh ...

  8. 数据库中间件ShardingSphere-Proxy(一)

    1.现实中的问题 我们知道数据库的数据,基本80%的业务是查询,20%的业务涵盖了增删改,经过长期的业务变更和积累数据库的数据到达了一定的数量之后,直接影响的是用户与系统的交互,查询时的速度,插入数据 ...

  9. MyCat:取代Cobar数据库中间件

    什么是MyCAT?简单的说,MyCAT就是: 一个彻底开源的,面向企业应用开发的“大数据库集群” 支持事务.ACID.可以替代Mysql的加强版数据库 ? 一个可以视为“Mysql”集群的企业级数据库 ...

随机推荐

  1. 巧用 PHP 数组函数

    0x00 前言 PHP 的数组是一种很强大的数据类型,与此同时 PHP 内置了一系列与数组相关的函数可以很轻易的实现日常开发的功能.但是我发现好像很多小伙伴都忽略了内置函数的作用(比如我自己就编写过一 ...

  2. Libev源码分析06:异步信号同步化--sigwait、sigwaitinfo、sigtimedwait和signalfd

    一:信号简述 信号是典型的异步事件.内核在某个信号出现时有三种处理方式: a:忽略信号,除了SIGKILL和SIGSTOP信号不能忽略外,其他大部分信号都可以被忽略: b:捕捉信号,也就是在信号发生时 ...

  3. 从遇见到信任 | Apache Dubbo 的毕业之旅

    所谓信任,就是多一次机会. 2018年2月16日,Apache Dubbo 加入 Apache 基金会孵化器. ... 2019年5月16日,Apache 软件基金会董事会决议通过了 Apache D ...

  4. jq获取单选框、复选框、下拉菜单的值

    1.<input type="radio" name="testradio" value="jquery获取radio的值" /> ...

  5. GPU版TensorFlow怎么指定让CPU运行

    由于某些原因GPU版的TensorFlow运行起来会出现一些问题,比如内存溢出等情况.此时我们可以用CPU和系统内存来运行我们的程序. 代码如下: import osos.environ[" ...

  6. java el表达式报空指针异常(nullpointexception)

    最近在使用el表达式的时候,用到了int型变量,因为,很多时候,变量不会被赋初值,后面考虑了下,应该将声明由int 改为integer,改了之后就一直报空指针异常,后面仔细查看,我的getter和se ...

  7. 2014年NOIP普及组复赛题解

    题目涉及算法: 珠心算测验:枚举: 比例简化:枚举: 螺旋矩阵:模拟: 子矩阵:状态压缩/枚举/动态规划 珠心算测验 题目链接:https://www.luogu.org/problem/P2141 ...

  8. 智课雅思短语---三、unshakable duty

    智课雅思短语---三.unshakable duty 一.总结 一句话总结:不可推卸的义务 unshakable duty 1.satisfy/ meet the needs of…? 满足需求 2. ...

  9. Spring Security实现禁止用户重复登陆(配置及原理)

    系统使用了Spring Security做权限管理,现在对于系统的用户,需要改动配置,实现无法多地登陆.   一.SpringMVC项目,配置如下: 首先在修改Security相关的XML,我这里是s ...

  10. 2018-8-10-C#-代码占用的空间

    title author date CreateTime categories C# 代码占用的空间 lindexi 2018-08-10 19:16:52 +0800 2018-2-13 17:23 ...