MyCat - 使用篇(5)
此文已由作者张镐薪授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
意思就是,开头为北京的范围在A0000000~A9999999的根据后面的哈希值对5取模平均分布在0,1,2,3,4分片节点上。开头为北京的范围在B0000000以上的根据后面的哈希值对5取模平均分布在5,6,7,8,9分片节点上。开头为上海的范围在00000000~10000000的根据后面的哈希值对2取模平均分布在10,11分片节点上,剩下的开头为上海的,对6取模平均分布在10,11,12,13,14,15上。 这样,在发现某个开头的分片不够用时,可以随时改变分片规则,只要不删除之前的分片规则,就不影响以前数据的访问。在完成数据迁移后,可以删除之前的规则。 实现方法就是采用hashmap存储这些对应关系:
/**
* 首先实现不带范围约定的复合规则,即配置文件中为:
* 北京=0,1,2,3,4
* 上海=10,11
*/public class PartitionByRouteHash extends AbstractPartitionAlgorithm implements RuleAlgorithm { protected String routeFile; private Map<String, List<Integer>> routeNodeMap; protected static final String DEFAULT_NODE = "DEFAULT_NODE"; protected int keyStartIndex; protected int keyEndIndex; protected int valueStartIndex; protected int valueEndIndex; public void setKeyStartIndex(int keyStartIndex) { this.keyStartIndex = keyStartIndex;
} public void setKeyEndIndex(int keyEndIndex) { this.keyEndIndex = keyEndIndex;
} public void setValueStartIndex(int valueStartIndex) { this.valueStartIndex = valueStartIndex;
} public void setValueEndIndex(int valueEndIndex) { this.valueEndIndex = valueEndIndex;
} public void setRouteFile(String routeFile) { this.routeFile = routeFile;
} @Override public void init() {
initialize();
}
@Override public Integer calculate(String columnValue) {
String key = columnValue.substring(keyStartIndex,keyEndIndex);
String value = columnValue.substring(valueStartIndex,valueEndIndex);
List<Integer> nodes = routeNodeMap.get(key); if(nodes == null)
nodes = routeNodeMap.get(DEFAULT_NODE);
BigInteger bigNum = new BigInteger(""+value.hashCode()); return nodes.get((bigNum.mod(BigInteger.valueOf(nodes.size()))).intValue());
} /**
* 读取文件,创建哈希表保存对应关系
*/
private void initialize() {
BufferedReader in = null; try { // FileInputStream fin = new FileInputStream(new File(fileMapPath));
InputStream fin = this.getClass().getClassLoader()
.getResourceAsStream(routeFile); if (fin == null) { throw new RuntimeException("can't find class resource file "
+ routeFile);
} in = new BufferedReader(new InputStreamReader(fin)); routeNodeMap = new HashMap<String, List<Integer>>(); for (String line = null; (line = in.readLine()) != null;) {
line = line.trim(); if (line.startsWith("#") || line.startsWith("//")) continue; int ind = line.indexOf('='); if (ind < 0) continue; try {
String key = line.substring(0, ind).trim();
String value = line.substring(ind+1).trim();
String []nodes = value.split(",");
List<Integer> values = new ArrayList<Integer>(); for(int i = 0 ; i< nodes.length ; i++){
values.add(Integer.parseInt(nodes[i].trim()));
}
routeNodeMap.put(key,values);
} catch (Exception e) {
System.out.println("something wrong in the route hash configuration!");
}
}
} catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e;
} else { throw new RuntimeException(e);
} } finally { try { in.close();
} catch (Exception e2) {
}
}
}
}
/**
* 实现范围约定的复合规则
*/public class PartitionByScalableRouteHash extends PartitionByRouteHash { private Map<String,Map<String[],List<Integer>>> routeNodeMap; @Override public void init() {
initialize();
} @Override public Integer calculate(String columnValue) {
String key = columnValue.substring(keyStartIndex,keyEndIndex);
String value = columnValue.substring(valueStartIndex,valueEndIndex);
Map<String[],List<Integer>> scaleMap = routeNodeMap.get(key); if(scaleMap==null){
scaleMap = routeNodeMap.get(this.DEFAULT_NODE);
}
String []ranges = new String[1]; for(String []range:scaleMap.keySet()){ if(range[0].equals(this.DEFAULT_NODE)) continue; if(range[0].compareTo(value)<0&&range[1].compareTo(value)>0)
ranges = range;
} if(ranges.length==1) { for(String []range:scaleMap.keySet()){ if(range[0].equals(this.DEFAULT_NODE)){
ranges = range; break;
}
}
}
List<Integer> nodes = scaleMap.get(ranges);
BigInteger bigNum = new BigInteger(""+value.hashCode()); return nodes.get((bigNum.mod(BigInteger.valueOf(nodes.size()))).intValue());
} private void initialize(){
BufferedReader in = null; try { // FileInputStream fin = new FileInputStream(new File(fileMapPath));
InputStream fin = this.getClass().getClassLoader()
.getResourceAsStream(routeFile); if (fin == null) { throw new RuntimeException("can't find class resource file "
+ routeFile);
} in = new BufferedReader(new InputStreamReader(fin)); routeNodeMap = new HashMap<String, Map<String[], List<Integer>>>(); for (String line = null; (line = in.readLine()) != null;) {
line = line.trim(); if (line.startsWith("#") || line.startsWith("//")) continue; int lb = line.indexOf('('),rb = line.indexOf(')'),mb = line.indexOf(':'); int ind = line.indexOf('='); if((lb!=-1&&rb!=-1&&mb!=-1)&&(mb<lb||mb>rb||lb>rb||rb>ind)){ throw new RuntimeException("Wrong format! Error use of (),:,=!");
} if (ind < 0) continue; try {
String key = line.substring(0, lb<0?ind:lb).trim();
Map<String[],List<Integer>> scaleMap = routeNodeMap.get(key); if(scaleMap == null){
scaleMap = new HashMap<String[],List<Integer>>();
routeNodeMap.put(key,scaleMap);
}
String[] valueRange = new String[2]; if(lb!=-1&&rb!=-1&&mb!=-1) {
String minValue = line.substring(lb + 1, mb).trim();
String maxValue = line.substring(mb + 1, rb).trim(); if (minValue.length() != maxValue.length() || minValue.compareTo(maxValue) >= 0) { throw new RuntimeException("Wrong value range! ");
}
valueRange[0] = minValue;
valueRange[1] = maxValue;
} else {
valueRange[0] = this.DEFAULT_NODE;
}
String value = line.substring(ind+1).trim();
String []nodes = value.split(",");
List<Integer> node = new ArrayList<Integer>(); for(int i = 0 ; i< nodes.length ; i++){
node.add(Integer.parseInt(nodes[i].trim()));
}
scaleMap.put(valueRange,node);
} catch (Exception e) {
System.out.println("something wrong in the route hash configuration!");
}
}
} catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e;
} else { throw new RuntimeException(e);
} } finally { try { in.close();
} catch (Exception e2) {
}
}
} }
之后如果想用这个规则,在rule.xml中添加如下配置即可:
<tableRule name="scalable-route-hash">
<rule>
<columns>order_id</columns>
<algorithm>scalable-route-hash</algorithm>
</rule>
</tableRule>
<function name="scalable-route-hash" class="org.opencloudb.route.function.PartitionByRouteHash">
<property name="routeFile">scalable-route-hash.txt</property>
<property name="keyStartIndex">0</property>
<property name="keyEndIndex">5</property>
<property name="valueStartIndex">5</property>
<property name="valueEndIndex">11</property>
</function>
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 Gradle task
【推荐】 debian 7上源码编译MongoDB 3.4版本
【推荐】 新手入门Sqlalchemy
MyCat - 使用篇(5)的更多相关文章
- MyCat - 使用篇
Mycat水平拆分之十种分片规则: http://www.cnblogs.com/756623607-zhang/p/6656022.html 数据库路由中间件MyCat - 使用篇(5) 配置MyC ...
- MyCat - 背景篇(1)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. SQL与NoSQL 目前,对于互联网海量数据的存储以及处理,按使用场景,分为OLTP(联机事务处理,比如即时 ...
- 数据库路由中间件MyCat - 源代码篇(15)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. public static void handle(String stmt, ServerConnectio ...
- 数据库路由中间件MyCat - 使用篇(1)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 基本概念 直接介绍概念太枯燥了,还是拿个和背景篇相似的例子介绍 业务场景:客户完成下单,快递员接受并更新运单 ...
- 数据库路由中间件MyCat - 源代码篇(13)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 4.配置模块 4.2 schema.xml 接上一篇,接下来载入每个schema的配置(也就是每个MyCat ...
- 数据库路由中间件MyCat - 源代码篇(1)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 进入了源代码篇,我们先从整体入手,之后拿一个简单流程前端连接建立与认证作为例子,理清代码思路和设计模式.然后 ...
- 数据库路由中间件MyCat - 使用篇(4)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 配置MyCat 3. 配置conf/rule.xml 1.5GA版本中的规则配置比较笨,2.0中优化了一些, ...
- 数据库路由中间件MyCat - 使用篇(3)下篇
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2. 配置conf/server.xml server.xml几乎保存了所有mycat需要的系统配置信息.其 ...
- 数据库路由中间件MyCat - 使用篇(3)上篇
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 全局序列号 数据切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用,因此需要引入外部机制保证数据唯 ...
- 数据库路由中间件MyCat - 源代码篇(7)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3. 连接模块 3.4 FrontendConnection前端连接 构造方法: public Fronte ...
随机推荐
- 用于string对象中字符截取的几种函数总结——语法、参数意义及用途举例
1. charAt():返回指定位置的字符. 语法:stringObject.charAt(index) 参数意义:index 必需,指字符在字符串中的下标.需要注意的是,字符串中第一个字符的下标是 ...
- FI模块与SD、MM的接口配置方法
[转自 http://blog.itpub.net/195776/viewspace-1023910/] 1 FI/SD 借口配置FI/SD通过tcode VKOA为billing设置过帐科目,用户可 ...
- 微信小程序开发:学习笔记[1]——Hello World
微信小程序开发:学习笔记[1]——Hello World 快速开始 1.前往微信公众平台下载微信开发者工具. 地址:https://mp.weixin.qq.com/debug/wxadoc/dev/ ...
- PAT 甲级 1028. List Sorting (25) 【结构体排序】
题目链接 https://www.patest.cn/contests/pat-a-practise/1028 思路 就按照 它的三种方式 设计 comp 函数 然后快排就好了 但是 如果用 c++ ...
- ajax 异步 跨域上传图片
客户端 <label for="text">名称</label> <input type="text" id="text ...
- Spring Boot2.0之全局捕获异常
全局捕获异常,很明显的错误404返回给客户,很不好呀.整个web请求项目全局捕获异常,比如空指针直接返回给客户啊,那多操蛋呀~ 看这几个常用的注解: @ExceptionHandler 表示拦截异常 ...
- 算法(Algorithms)第4版 练习 1.3.23 1.3.22
1.3.23 When it comes time to update t.next, x.next is no longer the original node following x, but i ...
- 【详解】苹果AppStore审核被拒,原因终逃不过这些!
近日,相信很多开发者都留意到了: 苹果针对应用标题的审核确有明显的变严趋势!我们在<惊!苹果再次加强审核力度,众App纷纷止步应用标题>中也对该现象进行了详细的分析,并给出了相应的解决方案 ...
- 英语影视台词---无敌破坏王2大脑互联网(3)((Ralph)我们去喝根汁汽水吧)
英语影视台词---无敌破坏王2大脑互联网(3)((Ralph)我们去喝根汁汽水吧) 一.总结 一句话总结: Let's go get a root beer. 1.(Ralph)让我来瞧瞧你的本事 ...
- PHP读取xml方法介绍
一,什么是xml,xml有什么用途 XML(Extensible Markup Language)即可扩展标记语言,它与HTML一样,都是SGML(Standard Generalized Marku ...