此文已由作者张镐薪授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

意思就是,开头为北京的范围在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)的更多相关文章

  1. MyCat - 使用篇

    Mycat水平拆分之十种分片规则: http://www.cnblogs.com/756623607-zhang/p/6656022.html 数据库路由中间件MyCat - 使用篇(5) 配置MyC ...

  2. MyCat - 背景篇(1)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. SQL与NoSQL 目前,对于互联网海量数据的存储以及处理,按使用场景,分为OLTP(联机事务处理,比如即时 ...

  3. 数据库路由中间件MyCat - 源代码篇(15)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. public static void handle(String stmt, ServerConnectio ...

  4. 数据库路由中间件MyCat - 使用篇(1)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 基本概念 直接介绍概念太枯燥了,还是拿个和背景篇相似的例子介绍 业务场景:客户完成下单,快递员接受并更新运单 ...

  5. 数据库路由中间件MyCat - 源代码篇(13)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 4.配置模块 4.2 schema.xml 接上一篇,接下来载入每个schema的配置(也就是每个MyCat ...

  6. 数据库路由中间件MyCat - 源代码篇(1)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 进入了源代码篇,我们先从整体入手,之后拿一个简单流程前端连接建立与认证作为例子,理清代码思路和设计模式.然后 ...

  7. 数据库路由中间件MyCat - 使用篇(4)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 配置MyCat 3. 配置conf/rule.xml 1.5GA版本中的规则配置比较笨,2.0中优化了一些, ...

  8. 数据库路由中间件MyCat - 使用篇(3)下篇

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2. 配置conf/server.xml server.xml几乎保存了所有mycat需要的系统配置信息.其 ...

  9. 数据库路由中间件MyCat - 使用篇(3)上篇

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 全局序列号 数据切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用,因此需要引入外部机制保证数据唯 ...

  10. 数据库路由中间件MyCat - 源代码篇(7)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3. 连接模块 3.4 FrontendConnection前端连接 构造方法: public Fronte ...

随机推荐

  1. Grunt学习笔记【7】---- grunt-contrib-less插件详解

    本文主要讲如何使用Grunt实现less文件压缩. 一 说明 less是非常常用的样式框架之一,Grunt也提供了可以编译和打包less样式文件的插件:grunt-contrib-less. 实现原理 ...

  2. OCR光学字符识别--STN-OCR 测试

    1.同文章中建议的使用ubuntu-python隔离环境,真的很好用 参照:http://blog.topspeedsnail.com/archives/5618启动虚拟环境:source env/b ...

  3. 【题解】Coins(二进制拆分+bitset)

    [题解]Coins(二进制拆分+bitset) [vj] 俗话说得好,bitset大法吼啊 这道题要不是他多组数据卡死了我复杂度算出来等于九千多万的选手我还不会想这种好办法233 考虑转移的实质是怎样 ...

  4. 改善程序与设计的55个具体做法 day1

    博客好久没更新了,就从这本读书笔记开始吧. 条款01: 视C++为一个语言联邦 C++可视为有四个次语言组成的: 1.C语言 2.Object-Oriented C++ (面向对象C++) 3.Tem ...

  5. gradle 添加依赖

    files 添加libs下的 project 添加一个module compile 去下载一个

  6. MVC+Ext.net零基础学习记录(一)

    由于最近开发一个项目,决定使用MVC+EXT.NET,决定将学习的这个过程记录下来 本人和很多菜鸟一样,之前既没有使用过MVC开发,也没有接触过EXT.NET,所以这将是一个大家共同学习的过程,文章中 ...

  7. 学习c语言的第14天

    #include <stdio.h> #include <string.h> struct student { int age; char sex; char name[100 ...

  8. Android Studio 主题、字体大小的设置

    1. Android Studio 主题的设置: 设置Android Studio 自带的主题 设置第三方主题 2. Android Studio 字体的设置 设置左面包名的字体大小 设置右面代码编辑 ...

  9. hdu-5793 A Boring Question(二项式定理)

    题目链接: A Boring Question Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java ...

  10. codeforces 658C C. Bear and Forgotten Tree 3(tree+乱搞)

    题目链接: C. Bear and Forgotten Tree 3 time limit per test 2 seconds memory limit per test 256 megabytes ...