加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

Mysql系列六:(Mycat分片路由原理、Mycat常用分片规则及对应源

发布时间:2020-12-11 23:57:40 所属栏目:MySql教程 来源:网络整理
导读:?一、Mycat分片路由原理 我们先来看下面的一个SQL在Mycat里面是如何执行的: travelrecord id ( , ); 有3个分片dn1,dn2,dn3,id=5000001 查询时可能有出现的问题: dn1 ?dn2 ?dn3 2)只扫描某个片。漏掉数据的情况。 那么Mycat是如何解决上面的问题的呢? Myc

?一、Mycat分片路由原理

我们先来看下面的一个SQL在Mycat里面是如何执行的:

travelrecord id (,);

有3个分片dn1,dn2,dn3,id=5000001

查询时可能有出现的问题:

dn1 ?dn2 ?dn3

2)只扫描某个片。漏掉数据的情况。

那么Mycat是如何解决上面的问题的呢?

Mycat解析的过程主要有Visitor和Statement两个阶段

1)Visitor过程,解析出如下属性:

              哪一张表

              字段列表

              条件信息

              什么样的SQL

通过查询条件可以知道要查询的数据都在哪些分片上

travelrecord id travelrecord id ;(dn3执行)

4)分别在分片dn2,dn3上执行第 3)步改写的SQL,然后把从dn2,dn3上得到的结果进行拼装就是最终的结果了

visitor

确定分片的过程:首先看where

二、Mycat常用分片规则

1. 时间类:按天分片、自然月分片、单月小时分片

2. 哈希类:Hash固定分片、日期范围Hash分片、截取数字Hash求模范围分片、截取数字Hash分片、一致性Hash分片

3. 取模类:取模分片、取模范围分片、范围求模分片

4. 其他类:枚举分片、范围约定分片、应用指定分片、冷热数据分片

下面基于源码来介绍Mycat的常用分片规则,

三、Mycat常用分片规则介绍

分片规则都定义在rule.xml文件里面

id func1 1,1,2,3,1 128,128,128

1. 自动范围分片

在rule.xml里面的配置:

id rang-long

<span style="color: #0000ff"><<span style="color: #800000">function <span style="color: #ff0000">name<span style="color: #0000ff">="rang-long"<span style="color: #ff0000">
class<span style="color: #0000ff">="io.mycat.route.function.AutoPartitionByLong"<span style="color: #0000ff">>
<span style="color: #0000ff"><<span style="color: #800000">property <span style="color: #ff0000">name<span style="color: #0000ff">="mapFile"<span style="color: #0000ff">>autopartition-long.txt<span style="color: #0000ff"></<span style="color: #800000">property<span style="color: #0000ff">>
<span style="color: #0000ff"></<span style="color: #800000">function<span style="color: #0000ff">>

说明:

有3个分片,第1个分片存储的是1-500000的数据,第2个分片存储的是500001-1000000的数据,第3个分片存储的是1000001-1500000的数据

insert into employee(id,name) value(1,Tom);在第1个分片

insert into employee(id,name) value(500002,Jack);在第2个分片

insert into employee(id,name) value(1000002,Lucy);在第3个分片

对应代码:

<span style="color: #0000ff">import<span style="color: #000000"> java.io.BufferedReader;
<span style="color: #0000ff">import
<span style="color: #000000"> java.io.InputStream;
<span style="color: #0000ff">import
<span style="color: #000000"> java.io.InputStreamReader;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.HashSet;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.LinkedList;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.Set;

<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.config.model.rule.RuleAlgorithm;

<span style="color: #008000">/**<span style="color: #008000">

  • auto partition by Long,can be used in auto increment primary key partition

  • <span style="color: #808080">@author<span style="color: #008000"> wuzhi
    <span style="color: #008000">*/
    <span style="color: #0000ff">public <span style="color: #0000ff">class AutoPartitionByLong <span style="color: #0000ff">extends AbstractPartitionAlgorithm <span style="color: #0000ff">implements<span style="color: #000000"> RuleAlgorithm{

    <span style="color: #0000ff">private<span style="color: #000000"> String mapFile;
    <span style="color: #0000ff">private<span style="color: #000000"> LongRange[] longRongs;

    <span style="color: #0000ff">private <span style="color: #0000ff">int defaultNode = -1<span style="color: #000000">;
    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> init() {

     initialize();

    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setMapFile(String mapFile) {
    <span style="color: #0000ff">this.mapFile =<span style="color: #000000"> mapFile;
    }

    @Override
    <span style="color: #0000ff">public<span style="color: #000000"> Integer calculate(String columnValue) {
    <span style="color: #008000">//<span style="color: #008000"> columnValue = NumberParseUtil.eliminateQoute(columnValue);
    <span style="color: #0000ff">try<span style="color: #000000"> {
    <span style="color: #0000ff">long value =<span style="color: #000000"> Long.parseLong(columnValue);
    Integer rst = <span style="color: #0000ff">null<span style="color: #000000">;
    <span style="color: #0000ff">for (LongRange longRang : <span style="color: #0000ff">this<span style="color: #000000">.longRongs) {
    <span style="color: #0000ff">if (value <= longRang.valueEnd && value >=<span style="color: #000000"> longRang.valueStart) {
    <span style="color: #0000ff">return<span style="color: #000000"> longRang.nodeIndx;
    }
    }
    <span style="color: #008000">//<span style="color: #008000">数据超过范围,暂时使用配置的默认节点
    <span style="color: #0000ff">if (rst == <span style="color: #0000ff">null && defaultNode >= 0<span style="color: #000000">) {
    <span style="color: #0000ff">return<span style="color: #000000"> defaultNode;
    }
    <span style="color: #0000ff">return<span style="color: #000000"> rst;
    } <span style="color: #0000ff">catch<span style="color: #000000"> (NumberFormatException e){
    <span style="color: #0000ff">throw <span style="color: #0000ff">new IllegalArgumentException(<span style="color: #0000ff">new StringBuilder().append("columnValue:").append(columnValue).append(" Please eliminate any quote and non number within it."<span style="color: #000000">).toString(),e);
    }
    }

    @Override
    <span style="color: #0000ff">public<span style="color: #000000"> Integer[] calculateRange(String beginValue,String endValue) {
    <span style="color: #0000ff">return AbstractPartitionAlgorithm.calculateSequenceRange(<span style="color: #0000ff">this<span style="color: #000000">,beginValue,endValue);
    }

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">int<span style="color: #000000"> getPartitionNum() {
    <span style="color: #008000">//<span style="color: #008000"> int nPartition = longRongs.length;

     <span style="color: #008000"&gt;/*</span><span style="color: #008000"&gt;
      * fix #1284 这里的统计应该统计Range的nodeIndex的distinct总数
      </span><span style="color: #008000"&gt;*/</span><span style="color: #000000"&gt;
     Set</span><Integer> distNodeIdxSet = <span style="color: #0000ff"&gt;new</span> HashSet<Integer><span style="color: #000000"&gt;();
     </span><span style="color: #0000ff"&gt;for</span><span style="color: #000000"&gt;(LongRange range : longRongs) {
         distNodeIdxSet.add(range.nodeIndx);
     }
     </span><span style="color: #0000ff"&gt;int</span> nPartition =<span style="color: #000000"&gt; distNodeIdxSet.size();
     </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; nPartition;

    }

    <span style="color: #0000ff">private <span style="color: #0000ff">void<span style="color: #000000"> initialize() {
    BufferedReader in = <span style="color: #0000ff">null<span style="color: #000000">;
    <span style="color: #0000ff">try<span style="color: #000000"> {
    <span style="color: #008000">//<span style="color: #008000"> FileInputStream fin = new FileInputStream(new File(fileMapPath));
    InputStream fin = <span style="color: #0000ff">this<span style="color: #000000">.getClass().getClassLoader()
    .getResourceAsStream(mapFile);
    <span style="color: #0000ff">if (fin == <span style="color: #0000ff">null<span style="color: #000000">) {
    <span style="color: #0000ff">throw <span style="color: #0000ff">new RuntimeException("can't find class resource file "
    +<span style="color: #000000"> mapFile);
    }
    in = <span style="color: #0000ff">new BufferedReader(<span style="color: #0000ff">new<span style="color: #000000"> InputStreamReader(fin));
    LinkedList longRangeList = <span style="color: #0000ff">new LinkedList<span style="color: #000000">();

         </span><span style="color: #0000ff"&gt;for</span> (String line = <span style="color: #0000ff"&gt;null</span>; (line = in.readLine()) != <span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;;) {
             line </span>=<span style="color: #000000"&gt; line.trim();
             </span><span style="color: #0000ff"&gt;if</span> (line.startsWith("#") || line.startsWith("//"<span style="color: #000000"&gt;)) {
                 </span><span style="color: #0000ff"&gt;continue</span><span style="color: #000000"&gt;;
             }
             </span><span style="color: #0000ff"&gt;int</span> ind = line.indexOf('='<span style="color: #000000"&gt;);
             </span><span style="color: #0000ff"&gt;if</span> (ind < 0<span style="color: #000000"&gt;) {
                 System.out.println(</span>" warn: bad line int " + mapFile + " :"
                         +<span style="color: #000000"&gt; line);
                 </span><span style="color: #0000ff"&gt;continue</span><span style="color: #000000"&gt;;
             }
                 String pairs[] </span>= line.substring(0,ind).trim().split("-"<span style="color: #000000"&gt;);
                 </span><span style="color: #0000ff"&gt;long</span> longStart = NumberParseUtil.parseLong(pairs[0<span style="color: #000000"&gt;].trim());
                 </span><span style="color: #0000ff"&gt;long</span> longEnd = NumberParseUtil.parseLong(pairs[1<span style="color: #000000"&gt;].trim());
                 </span><span style="color: #0000ff"&gt;int</span> nodeId = Integer.parseInt(line.substring(ind + 1<span style="color: #000000"&gt;)
                         .trim());
                 longRangeList
                         .add(</span><span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; LongRange(nodeId,longStart,longEnd));
    
         }
         longRongs </span>= longRangeList.toArray(<span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; LongRange[longRangeList
                 .size()]);
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (Exception e) {
         </span><span style="color: #0000ff"&gt;if</span> (e <span style="color: #0000ff"&gt;instanceof</span><span style="color: #000000"&gt; RuntimeException) {
             </span><span style="color: #0000ff"&gt;throw</span><span style="color: #000000"&gt; (RuntimeException) e;
         } </span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt; {
             </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; RuntimeException(e);
         }
    
     } </span><span style="color: #0000ff"&gt;finally</span><span style="color: #000000"&gt; {
         </span><span style="color: #0000ff"&gt;try</span><span style="color: #000000"&gt; {
             in.close();
         } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (Exception e2) {
         }
     }

    }

    <span style="color: #0000ff">public <span style="color: #0000ff">int<span style="color: #000000"> getDefaultNode() {
    <span style="color: #0000ff">return<span style="color: #000000"> defaultNode;
    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void setDefaultNode(<span style="color: #0000ff">int<span style="color: #000000"> defaultNode) {
    <span style="color: #0000ff">this.defaultNode =<span style="color: #000000"> defaultNode;
    }

    <span style="color: #0000ff">static <span style="color: #0000ff">class<span style="color: #000000"> LongRange {
    <span style="color: #0000ff">public <span style="color: #0000ff">final <span style="color: #0000ff">int<span style="color: #000000"> nodeIndx;
    <span style="color: #0000ff">public <span style="color: #0000ff">final <span style="color: #0000ff">long<span style="color: #000000"> valueStart;
    <span style="color: #0000ff">public <span style="color: #0000ff">final <span style="color: #0000ff">long<span style="color: #000000"> valueEnd;

     </span><span style="color: #0000ff"&gt;public</span> LongRange(<span style="color: #0000ff"&gt;int</span> nodeIndx,<span style="color: #0000ff"&gt;long</span> valueStart,<span style="color: #0000ff"&gt;long</span><span style="color: #000000"&gt; valueEnd) {
         </span><span style="color: #0000ff"&gt;super</span><span style="color: #000000"&gt;();
         </span><span style="color: #0000ff"&gt;this</span>.nodeIndx =<span style="color: #000000"&gt; nodeIndx;
         </span><span style="color: #0000ff"&gt;this</span>.valueStart =<span style="color: #000000"&gt; valueStart;
         </span><span style="color: #0000ff"&gt;this</span>.valueEnd =<span style="color: #000000"&gt; valueEnd;
     }

    }
    }

    2. 枚举分片

    把数据分类存储

    在rule.xml里面的配置:

    sharding_id hash-int partition-hash-int.txt 0

    说明:0

    对应代码:

<span style="color: #0000ff">import<span style="color: #000000"> java.io.BufferedReader;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.InputStream;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.InputStreamReader;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.HashMap;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.HashSet;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.Map;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.Set;

<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.config.model.rule.RuleAlgorithm;

<span style="color: #008000">/**<span style="color: #008000">

  • <span style="color: #808080">@author<span style="color: #008000"> mycat
    <span style="color: #008000">*/
    <span style="color: #0000ff">public <span style="color: #0000ff">class PartitionByFileMap <span style="color: #0000ff">extends AbstractPartitionAlgorithm <span style="color: #0000ff">implements<span style="color: #000000"> RuleAlgorithm {

    <span style="color: #0000ff">private<span style="color: #000000"> String mapFile;
    <span style="color: #0000ff">private Map<Object,Integer><span style="color: #000000"> app2Partition;
    <span style="color: #008000">/**<span style="color: #008000">

    • Map<Object,Integer> app2Partition中key值的类型:默认值为0,0表示Integer,非零表示String
      <span style="color: #008000">*/
      <span style="color: #0000ff">private <span style="color: #0000ff">int<span style="color: #000000"> type;

    <span style="color: #008000">/**<span style="color: #008000">

    • 默认节点在map中的key
      <span style="color: #008000">*/
      <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">final String DEFAULT_NODE = "DEFAULT_NODE"<span style="color: #000000">;

    <span style="color: #008000">/**<span style="color: #008000">

    • 默认节点:小于0表示不设置默认节点,大于等于0表示设置默认节点
    • 默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点
    • 如果不配置默认节点(defaultNode值小于0表示不配置默认节点),碰到
    • 不识别的枚举值就会报错,
    • like this:can't find datanode for sharding column:column_name val:ffffffff
      <span style="color: #008000">*/
      <span style="color: #0000ff">private <span style="color: #0000ff">int defaultNode = -1<span style="color: #000000">;

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> init() {

     initialize();

    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setMapFile(String mapFile) {
    <span style="color: #0000ff">this.mapFile =<span style="color: #000000"> mapFile;
    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void setType(<span style="color: #0000ff">int<span style="color: #000000"> type) {
    <span style="color: #0000ff">this.type =<span style="color: #000000"> type;
    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void setDefaultNode(<span style="color: #0000ff">int<span style="color: #000000"> defaultNode) {
    <span style="color: #0000ff">this.defaultNode =<span style="color: #000000"> defaultNode;
    }

    @Override
    <span style="color: #0000ff">public<span style="color: #000000"> Integer calculate(String columnValue) {
    <span style="color: #0000ff">try<span style="color: #000000"> {
    Object value =<span style="color: #000000"> columnValue;
    <span style="color: #0000ff">if (type == 0<span style="color: #000000">) {
    value =<span style="color: #000000"> Integer.valueOf(columnValue);
    }
    Integer rst = <span style="color: #0000ff">null<span style="color: #000000">;
    Integer pid =<span style="color: #000000"> app2Partition.get(value);
    <span style="color: #0000ff">if (pid != <span style="color: #0000ff">null<span style="color: #000000">) {
    rst =<span style="color: #000000"> pid;
    } <span style="color: #0000ff">else<span style="color: #000000"> {
    rst =<span style="color: #000000"> app2Partition.get(DEFAULT_NODE);
    }
    <span style="color: #0000ff">return<span style="color: #000000"> rst;
    } <span style="color: #0000ff">catch<span style="color: #000000"> (NumberFormatException e){
    <span style="color: #0000ff">throw <span style="color: #0000ff">new IllegalArgumentException(<span style="color: #0000ff">new StringBuilder().append("columnValue:").append(columnValue).append(" Please check if the format satisfied."<span style="color: #000000">).toString(),e);
    }
    }

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">int<span style="color: #000000"> getPartitionNum() {
    Set set = <span style="color: #0000ff">new HashSet<span style="color: #000000">(app2Partition.values());
    <span style="color: #0000ff">int count =<span style="color: #000000"> set.size();
    <span style="color: #0000ff">return<span style="color: #000000"> count;
    }

    <span style="color: #0000ff">private <span style="color: #0000ff">void<span style="color: #000000"> initialize() {
    BufferedReader in = <span style="color: #0000ff">null<span style="color: #000000">;
    <span style="color: #0000ff">try<span style="color: #000000"> {
    <span style="color: #008000">//<span style="color: #008000"> FileInputStream fin = new FileInputStream(new File(fileMapPath));
    InputStream fin = <span style="color: #0000ff">this<span style="color: #000000">.getClass().getClassLoader()
    .getResourceAsStream(mapFile);
    <span style="color: #0000ff">if (fin == <span style="color: #0000ff">null<span style="color: #000000">) {
    <span style="color: #0000ff">throw <span style="color: #0000ff">new RuntimeException("can't find class resource file "
    +<span style="color: #000000"> mapFile);
    }
    in = <span style="color: #0000ff">new BufferedReader(<span style="color: #0000ff">new<span style="color: #000000"> InputStreamReader(fin));

         app2Partition </span>= <span style="color: #0000ff"&gt;new</span> HashMap<Object,Integer><span style="color: #000000"&gt;();
    
         </span><span style="color: #0000ff"&gt;for</span> (String line = <span style="color: #0000ff"&gt;null</span>; (line = in.readLine()) != <span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;;) {
             line </span>=<span style="color: #000000"&gt; line.trim();
             </span><span style="color: #0000ff"&gt;if</span> (line.startsWith("#") || line.startsWith("//"<span style="color: #000000"&gt;)) {
                 </span><span style="color: #0000ff"&gt;continue</span><span style="color: #000000"&gt;;
             }
             </span><span style="color: #0000ff"&gt;int</span> ind = line.indexOf('='<span style="color: #000000"&gt;);
             </span><span style="color: #0000ff"&gt;if</span> (ind < 0<span style="color: #000000"&gt;) {
                 </span><span style="color: #0000ff"&gt;continue</span><span style="color: #000000"&gt;;
             }
             </span><span style="color: #0000ff"&gt;try</span><span style="color: #000000"&gt; {
                 String key </span>= line.substring(0<span style="color: #000000"&gt;,ind).trim();
                 </span><span style="color: #0000ff"&gt;int</span> pid = Integer.parseInt(line.substring(ind + 1<span style="color: #000000"&gt;).trim());
                 </span><span style="color: #0000ff"&gt;if</span>(type == 0<span style="color: #000000"&gt;) {
                     app2Partition.put(Integer.parseInt(key),pid);
                 } </span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt; {
                     app2Partition.put(key,pid);
                 }
             } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (Exception e) {
             }
         }
         </span><span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;设置默认节点</span>
         <span style="color: #0000ff"&gt;if</span>(defaultNode >= 0<span style="color: #000000"&gt;) {
             app2Partition.put(DEFAULT_NODE,defaultNode);
         }
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (Exception e) {
         </span><span style="color: #0000ff"&gt;if</span> (e <span style="color: #0000ff"&gt;instanceof</span><span style="color: #000000"&gt; RuntimeException) {
             </span><span style="color: #0000ff"&gt;throw</span><span style="color: #000000"&gt; (RuntimeException) e;
         } </span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt; {
             </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; RuntimeException(e);
         }
    
     } </span><span style="color: #0000ff"&gt;finally</span><span style="color: #000000"&gt; {
         </span><span style="color: #0000ff"&gt;try</span><span style="color: #000000"&gt; {
             in.close();
         } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (Exception e2) {
         }
     }

    }
    }

    3. Hash固定分片(固定分片Hash算法)

    Hash

    在rule.xml里面的配置:

    id func1 1,128

    说明:

    1) partitionCount.length

    2) sum((partitionCount[i]*partitionLength[j])) === 1024——>partitionCount[0]*partitionLength[0]+partitionCount[1]*partitionLength[1] === 1024

    1*128+1*128+2*128+3*128+1*128 === 1024

    eg:

    8

    1

    2

    ...................

    8

    id

    id%1024 = 128

<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.config.model.rule.RuleAlgorithm;
<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.route.util.PartitionUtil;

<span style="color: #0000ff">public <span style="color: #0000ff">final <span style="color: #0000ff">class PartitionByLong <span style="color: #0000ff">extends AbstractPartitionAlgorithm <span style="color: #0000ff">implements<span style="color: #000000"> RuleAlgorithm {
<span style="color: #0000ff">protected <span style="color: #0000ff">int<span style="color: #000000">[] count;
<span style="color: #0000ff">protected <span style="color: #0000ff">int<span style="color: #000000">[] length;
<span style="color: #0000ff">protected<span style="color: #000000"> PartitionUtil partitionUtil;

</span><span style="color: #0000ff"&gt;private</span> <span style="color: #0000ff"&gt;static</span> <span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt;[] toIntArray(String string) {
    String[] strs </span>= io.mycat.util.SplitUtil.split(string,',<span style="color: #0000ff"&gt;true</span><span style="color: #000000"&gt;);
    </span><span style="color: #0000ff"&gt;int</span>[] ints = <span style="color: #0000ff"&gt;new</span> <span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt;[strs.length];
    </span><span style="color: #0000ff"&gt;for</span> (<span style="color: #0000ff"&gt;int</span> i = 0; i < strs.length; ++<span style="color: #000000"&gt;i) {
        ints[i] </span>=<span style="color: #000000"&gt; Integer.parseInt(strs[i]);
    }
    </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; ints;
}

</span><span style="color: #0000ff"&gt;public</span> <span style="color: #0000ff"&gt;void</span><span style="color: #000000"&gt; setPartitionCount(String partitionCount) {
    </span><span style="color: #0000ff"&gt;this</span>.count =<span style="color: #000000"&gt; toIntArray(partitionCount);
}

</span><span style="color: #0000ff"&gt;public</span> <span style="color: #0000ff"&gt;void</span><span style="color: #000000"&gt; setPartitionLength(String partitionLength) {
    </span><span style="color: #0000ff"&gt;this</span>.length =<span style="color: #000000"&gt; toIntArray(partitionLength);
}

@Override
</span><span style="color: #0000ff"&gt;public</span> <span style="color: #0000ff"&gt;void</span><span style="color: #000000"&gt; init() {
    partitionUtil </span>= <span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; PartitionUtil(count,length);

}

@Override
</span><span style="color: #0000ff"&gt;public</span><span style="color: #000000"&gt; Integer calculate(String columnValue)  {

<span style="color: #008000">//<span style="color: #008000"> columnValue = NumberParseUtil.eliminateQoute(columnValue);
<span style="color: #0000ff">try<span style="color: #000000"> {
<span style="color: #0000ff">long key =<span style="color: #000000"> Long.parseLong(columnValue);
<span style="color: #0000ff">return<span style="color: #000000"> partitionUtil.partition(key);
} <span style="color: #0000ff">catch<span style="color: #000000"> (NumberFormatException e){
<span style="color: #0000ff">throw <span style="color: #0000ff">new IllegalArgumentException(<span style="color: #0000ff">new StringBuilder().append("columnValue:").append(columnValue).append(" Please eliminate any quote and non number within it."<span style="color: #000000">).toString(),endValue);
}

<span style="color: #008000">//<span style="color: #008000"> @Override
<span style="color: #008000">//<span style="color: #008000"> public int getPartitionCount() {
<span style="color: #008000">//<span style="color: #008000"> int nPartition = 0;
<span style="color: #008000">//<span style="color: #008000"> for(int i = 0; i < count.length; i++) {
<span style="color: #008000">//<span style="color: #008000"> nPartition += count[i];
<span style="color: #008000">//<span style="color: #008000"> }
<span style="color: #008000">//<span style="color: #008000"> return nPartition;
<span style="color: #008000">//<span style="color: #008000"> }
<span style="color: #000000">
}

4.?求模分片

id%

在rule.xml里面的配置:

id mod-long 3

对应代码:

<span style="color: #0000ff">import<span style="color: #000000"> java.math.BigInteger;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.ArrayList;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.HashMap;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.List;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.Map;

<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.config.model.rule.RuleAlgorithm;

<span style="color: #008000">/**<span style="color: #008000">

  • number column partion by Mod operator

  • if count is 10 then 0 to 0,21 to 1 (21 % 10 =1)

  • <span style="color: #808080">@author<span style="color: #008000"> wuzhih

  • <span style="color: #008000">*/
    <span style="color: #0000ff">public <span style="color: #0000ff">class PartitionByMod <span style="color: #0000ff">extends AbstractPartitionAlgorithm <span style="color: #0000ff">implements<span style="color: #000000"> RuleAlgorithm {

    <span style="color: #0000ff">private <span style="color: #0000ff">int<span style="color: #000000"> count;
    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> init() {

    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void setCount(<span style="color: #0000ff">int<span style="color: #000000"> count) {
    <span style="color: #0000ff">this.count =<span style="color: #000000"> count;
    }

    @Override
    <span style="color: #0000ff">public<span style="color: #000000"> Integer calculate(String columnValue) {
    <span style="color: #008000">//<span style="color: #008000"> columnValue = NumberParseUtil.eliminateQoute(columnValue);
    <span style="color: #0000ff">try<span style="color: #000000"> {
    BigInteger bigNum = <span style="color: #0000ff">new<span style="color: #000000"> BigInteger(columnValue).abs();
    <span style="color: #0000ff">return<span style="color: #000000"> (bigNum.mod(BigInteger.valueOf(count))).intValue();
    } <span style="color: #0000ff">catch<span style="color: #000000"> (NumberFormatException e){
    <span style="color: #0000ff">throw <span style="color: #0000ff">new IllegalArgumentException(<span style="color: #0000ff">new StringBuilder().append("columnValue:").append(columnValue).append(" Please eliminate any quote and non number within it."<span style="color: #000000">).toString(),e);
    }

    }

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">int<span style="color: #000000"> getPartitionNum() {
    <span style="color: #0000ff">int nPartition = <span style="color: #0000ff">this<span style="color: #000000">.count;
    <span style="color: #0000ff">return<span style="color: #000000"> nPartition;
    }

    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">void<span style="color: #000000"> hashTest() {
    PartitionByMod hash=<span style="color: #0000ff">new<span style="color: #000000"> PartitionByMod();
    hash.setCount(11<span style="color: #000000">);
    hash.init();

     </span><span style="color: #0000ff"&gt;int</span>[] bucket=<span style="color: #0000ff"&gt;new</span> <span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt;[hash.count];
    
     Map</span><Integer,List<Integer>> hashed=<span style="color: #0000ff"&gt;new</span> HashMap<><span style="color: #000000"&gt;();
    
     </span><span style="color: #0000ff"&gt;int</span> total=1000_0000;<span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;数据量</span>
     <span style="color: #0000ff"&gt;int</span> c=0<span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span> i=100_0000;i<total+100_0000;i++){<span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;假设分片键从100万开始</span>
         c++<span style="color: #000000"&gt;;
         </span><span style="color: #0000ff"&gt;int</span> h=<span style="color: #000000"&gt;hash.calculate(Integer.toString(i));
         bucket[h]</span>++<span style="color: #000000"&gt;;
         List</span><Integer> list=<span style="color: #000000"&gt;hashed.get(h);
         </span><span style="color: #0000ff"&gt;if</span>(list==<span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;){
             list</span>=<span style="color: #0000ff"&gt;new</span> ArrayList<><span style="color: #000000"&gt;();
             hashed.put(h,list);
         }
         list.add(i);
     }
     System.out.println(c</span>+"   "+<span style="color: #000000"&gt;total);
     </span><span style="color: #0000ff"&gt;double</span> d=0<span style="color: #000000"&gt;;
     c</span>=0<span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;int</span> idx=0<span style="color: #000000"&gt;;
     System.out.println(</span>"index    bucket   ratio"<span style="color: #000000"&gt;);
     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt; i:bucket){
         d</span>+=i/(<span style="color: #0000ff"&gt;double</span><span style="color: #000000"&gt;)total;
         c</span>+=<span style="color: #000000"&gt;i;
         System.out.println(idx</span>+++"  "+i+"   "+(i/(<span style="color: #0000ff"&gt;double</span><span style="color: #000000"&gt;)total));
     }
     System.out.println(d</span>+"  "+<span style="color: #000000"&gt;c);
    
     System.out.println(</span>"****************************************************"<span style="color: #000000"&gt;);
     rehashTest(hashed.get(</span>0<span style="color: #000000"&gt;));

    }
    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">void rehashTest(List<span style="color: #000000"> partition) {
    PartitionByMod hash=<span style="color: #0000ff">new<span style="color: #000000"> PartitionByMod();
    hash.count=110;<span style="color: #008000">//<span style="color: #008000">分片数
    <span style="color: #000000"> hash.init();

     </span><span style="color: #0000ff"&gt;int</span>[] bucket=<span style="color: #0000ff"&gt;new</span> <span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt;[hash.count];
    
     </span><span style="color: #0000ff"&gt;int</span> total=partition.size();<span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;数据量</span>
     <span style="color: #0000ff"&gt;int</span> c=0<span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span> i:partition){<span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;假设分片键从100万开始</span>
         c++<span style="color: #000000"&gt;;
         </span><span style="color: #0000ff"&gt;int</span> h=<span style="color: #000000"&gt;hash.calculate(Integer.toString(i));
         bucket[h]</span>++<span style="color: #000000"&gt;;
     }
     System.out.println(c</span>+"   "+<span style="color: #000000"&gt;total);
     c</span>=0<span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;int</span> idx=0<span style="color: #000000"&gt;;
     System.out.println(</span>"index    bucket   ratio"<span style="color: #000000"&gt;);
     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt; i:bucket){
         c</span>+=<span style="color: #000000"&gt;i;
         System.out.println(idx</span>+++"  "+i+"   "+(i/(<span style="color: #0000ff"&gt;double</span><span style="color: #000000"&gt;)total));
     }

    }
    <span style="color: #0000ff">public <span style="color: #0000ff">static <span style="color: #0000ff">void<span style="color: #000000"> main(String[] args) {
    <span style="color: #008000">//<span style="color: #008000"> hashTest();
    PartitionByMod partitionByMod = <span style="color: #0000ff">new<span style="color: #000000"> PartitionByMod();
    partitionByMod.count=8<span style="color: #000000">;
    partitionByMod.calculate(""6""<span style="color: #000000">);
    partitionByMod.calculate("'6'"<span style="color: #000000">);
    }
    }

    5.?自然月分片

    按照自然月的方式进行分片

    在rule.xml里面的配置:

    create_time partbymonth yyyy-MM-dd 2015-01-01

    说明:

    sEndDated

    3

    分片

对应代码:

<span style="color: #0000ff">import<span style="color: #000000"> java.text.ParseException;
<span style="color: #0000ff">import
<span style="color: #000000"> java.text.SimpleDateFormat;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.ArrayList;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.Calendar;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.Collections;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.List;

<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.config.model.rule.RuleAlgorithm;
<span style="color: #0000ff">import<span style="color: #000000"> org.apache.log4j.Logger;

<span style="color: #008000">/**<span style="color: #008000">

  • 例子 按月份列分区 ,每个自然月一个分片,格式 between操作解析的范例

  • <span style="color: #808080">@author<span style="color: #008000"> wzh

  • <span style="color: #008000">*/
    <span style="color: #0000ff">public <span style="color: #0000ff">class PartitionByMonth <span style="color: #0000ff">extends AbstractPartitionAlgorithm <span style="color: #0000ff">implements<span style="color: #000000">
    RuleAlgorithm {
    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">final Logger LOGGER = Logger.getLogger(PartitionByDate.<span style="color: #0000ff">class<span style="color: #000000">);
    <span style="color: #0000ff">private<span style="color: #000000"> String sBeginDate;
    <span style="color: #0000ff">private<span style="color: #000000"> String dateFormat;
    <span style="color: #0000ff">private<span style="color: #000000"> String sEndDate;
    <span style="color: #0000ff">private<span style="color: #000000"> Calendar beginDate;
    <span style="color: #0000ff">private<span style="color: #000000"> Calendar endDate;
    <span style="color: #0000ff">private <span style="color: #0000ff">int<span style="color: #000000"> nPartition;

    <span style="color: #0000ff">private ThreadLocal<span style="color: #000000"> formatter;

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> init() {
    <span style="color: #0000ff">try<span style="color: #000000"> {
    beginDate =<span style="color: #000000"> Calendar.getInstance();
    beginDate.setTime(<span style="color: #0000ff">new<span style="color: #000000"> SimpleDateFormat(dateFormat)
    .parse(sBeginDate));
    formatter = <span style="color: #0000ff">new ThreadLocal<span style="color: #000000">() {
    @Override
    <span style="color: #0000ff">protected<span style="color: #000000"> SimpleDateFormat initialValue() {
    <span style="color: #0000ff">return <span style="color: #0000ff">new<span style="color: #000000"> SimpleDateFormat(dateFormat);
    }
    };
    <span style="color: #0000ff">if(sEndDate!=<span style="color: #0000ff">null&&!sEndDate.equals(""<span style="color: #000000">)) {
    endDate =<span style="color: #000000"> Calendar.getInstance();
    endDate.setTime(<span style="color: #0000ff">new<span style="color: #000000"> SimpleDateFormat(dateFormat).parse(sEndDate));
    nPartition = ((endDate.get(Calendar.YEAR) - beginDate.get(Calendar.YEAR)) * 12

    • endDate.get(Calendar.MONTH) - beginDate.get(Calendar.MONTH)) + 1<span style="color: #000000">;
             </span><span style="color: #0000ff"&gt;if</span> (nPartition <= 0<span style="color: #000000"&gt;) {
                 </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span> java.lang.IllegalArgumentException("Incorrect time range for month partitioning!"<span style="color: #000000"&gt;);
             }
         } </span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt; {
             nPartition </span>= -1<span style="color: #000000"&gt;;
         }
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (ParseException e) {
         </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; java.lang.IllegalArgumentException(e);
     }

    }

    <span style="color: #008000">/**<span style="color: #008000">

    • For circulatory partition,calculated value of target partition needs to be

    • rotated to fit the partition range
      <span style="color: #008000">*/
      <span style="color: #0000ff">private <span style="color: #0000ff">int reCalculatePartition(<span style="color: #0000ff">int<span style="color: #000000"> targetPartition) {
      <span style="color: #008000">/**<span style="color: #008000">

      • If target date is previous of start time of partition setting,shift
      • the delta range between target and start date to be positive value
        <span style="color: #008000">*/
        <span style="color: #0000ff">if (targetPartition < 0<span style="color: #000000">) {
        targetPartition = nPartition - (-targetPartition) %<span style="color: #000000"> nPartition;
        }

      <span style="color: #0000ff">if (targetPartition >=<span style="color: #000000"> nPartition) {
      targetPartition = targetPartition %<span style="color: #000000"> nPartition;
      }

      <span style="color: #0000ff">return<span style="color: #000000"> targetPartition;
      }

    @Override
    <span style="color: #0000ff">public<span style="color: #000000"> Integer calculate(String columnValue) {
    <span style="color: #0000ff">try<span style="color: #000000"> {
    <span style="color: #0000ff">int<span style="color: #000000"> targetPartition;
    Calendar curTime =<span style="color: #000000"> Calendar.getInstance();
    curTime.setTime(formatter.get().parse(columnValue));
    targetPartition = ((curTime.get(Calendar.YEAR) -<span style="color: #000000"> beginDate.get(Calendar.YEAR))
    * 12 +<span style="color: #000000"> curTime.get(Calendar.MONTH)
    -<span style="color: #000000"> beginDate.get(Calendar.MONTH));

         </span><span style="color: #008000"&gt;/**</span><span style="color: #008000"&gt;
          * For circulatory partition,calculated value of target partition needs to be
          * rotated to fit the partition range
           </span><span style="color: #008000"&gt;*/</span>
         <span style="color: #0000ff"&gt;if</span> (nPartition > 0<span style="color: #000000"&gt;) {
             targetPartition </span>=<span style="color: #000000"&gt; reCalculatePartition(targetPartition);
         }
         </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; targetPartition;
    
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (ParseException e) {
         </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span> IllegalArgumentException(<span style="color: #0000ff"&gt;new</span> StringBuilder().append("columnValue:").append(columnValue).append(" Please check if the format satisfied."<span style="color: #000000"&gt;).toString(),e);
     }

    }

    @Override
    <span style="color: #0000ff">public<span style="color: #000000"> Integer[] calculateRange(String beginValue,String endValue) {
    <span style="color: #0000ff">try<span style="color: #000000"> {
    <span style="color: #0000ff">int<span style="color: #000000"> startPartition,endPartition;
    Calendar partitionTime =<span style="color: #000000"> Calendar.getInstance();
    SimpleDateFormat format = <span style="color: #0000ff">new<span style="color: #000000"> SimpleDateFormat(dateFormat);
    partitionTime.setTime(format.parse(beginValue));
    startPartition = ((partitionTime.get(Calendar.YEAR) -<span style="color: #000000"> beginDate.get(Calendar.YEAR))
    12 +<span style="color: #000000"> partitionTime.get(Calendar.MONTH)
    -<span style="color: #000000"> beginDate.get(Calendar.MONTH));
    partitionTime.setTime(format.parse(endValue));
    endPartition = ((partitionTime.get(Calendar.YEAR) -<span style="color: #000000"> beginDate.get(Calendar.YEAR))
    12 +<span style="color: #000000"> partitionTime.get(Calendar.MONTH)
    -<span style="color: #000000"> beginDate.get(Calendar.MONTH));

         List</span><Integer> list = <span style="color: #0000ff"&gt;new</span> ArrayList<><span style="color: #000000"&gt;();
    
         </span><span style="color: #0000ff"&gt;while</span> (startPartition <=<span style="color: #000000"&gt; endPartition) {
             Integer nodeValue </span>=<span style="color: #000000"&gt; reCalculatePartition(startPartition);
             </span><span style="color: #0000ff"&gt;if</span> (Collections.frequency(list,nodeValue) < 1<span style="color: #000000"&gt;)
                 list.add(nodeValue);
             startPartition</span>++<span style="color: #000000"&gt;;
         }
         </span><span style="color: #0000ff"&gt;int</span> size =<span style="color: #000000"&gt; list.size();
         </span><span style="color: #0000ff"&gt;return</span> (list.toArray(<span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; Integer[size]));
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (ParseException e) {
         LOGGER.error(</span>"error"<span style="color: #000000"&gt;,e);
         </span><span style="color: #0000ff"&gt;return</span> <span style="color: #0000ff"&gt;new</span> Integer[0<span style="color: #000000"&gt;];
     }

    }

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">int<span style="color: #000000"> getPartitionNum() {
    <span style="color: #0000ff">int nPartition = <span style="color: #0000ff">this<span style="color: #000000">.nPartition;
    <span style="color: #0000ff">return<span style="color: #000000"> nPartition;
    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setsBeginDate(String sBeginDate) {
    <span style="color: #0000ff">this.sBeginDate =<span style="color: #000000"> sBeginDate;
    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setDateFormat(String dateFormat) {
    <span style="color: #0000ff">this.dateFormat =<span style="color: #000000"> dateFormat;
    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setsEndDate(String sEndDate) {
    <span style="color: #0000ff">this.sEndDate =<span style="color: #000000"> sEndDate;
    }

}

6.?匹配求模分片

prefixLengthcharAt(i)

在rule.xml里面的配置:

id partitionbyprefixpattern 3 6

有下面这种类型的数据

+

201801 01 ??10001

columns6

对应代码:

<span style="color: #0000ff">import<span style="color: #000000"> java.io.BufferedReader;
<span style="color: #0000ff">import
<span style="color: #000000"> java.io.InputStream;
<span style="color: #0000ff">import
<span style="color: #000000"> java.io.InputStreamReader;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.HashSet;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.LinkedList;
<span style="color: #0000ff">import
<span style="color: #000000"> java.util.Set;

<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.config.model.rule.RuleAlgorithm;
<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.route.function.AutoPartitionByLong.LongRange;

<span style="color: #008000">/**<span style="color: #008000">

  • partition by Prefix length,can be used in String partition

  • <span style="color: #808080">@author<span style="color: #008000"> hexiaobin
    <span style="color: #008000">*/
    <span style="color: #0000ff">public <span style="color: #0000ff">class PartitionByPrefixPattern <span style="color: #0000ff">extends AbstractPartitionAlgorithm <span style="color: #0000ff">implements<span style="color: #000000"> RuleAlgorithm {
    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">final <span style="color: #0000ff">int PARTITION_LENGTH = 1024<span style="color: #000000">;
    <span style="color: #0000ff">private <span style="color: #0000ff">int patternValue = PARTITION_LENGTH;<span style="color: #008000">//<span style="color: #008000"> 分区长度,取模数值(默认为1024)
    <span style="color: #0000ff">private <span style="color: #0000ff">int prefixLength;<span style="color: #008000">//<span style="color: #008000"> 字符前几位进行ASCII码取和
    <span style="color: #0000ff">private<span style="color: #000000"> String mapFile;
    <span style="color: #0000ff">private<span style="color: #000000"> LongRange[] longRongs;

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> init() {

     initialize();

    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setMapFile(String mapFile) {
    <span style="color: #0000ff">this.mapFile =<span style="color: #000000"> mapFile;
    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void setPatternValue(<span style="color: #0000ff">int<span style="color: #000000"> patternValue) {
    <span style="color: #0000ff">this.patternValue =<span style="color: #000000"> patternValue;
    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void setPrefixLength(<span style="color: #0000ff">int<span style="color: #000000"> prefixLength) {
    <span style="color: #0000ff">this.prefixLength =<span style="color: #000000"> prefixLength;
    }

    @Override
    <span style="color: #0000ff">public<span style="color: #000000"> Integer calculate(String columnValue) {
    <span style="color: #0000ff">try<span style="color: #000000"> {
    <span style="color: #0000ff">int Length =<span style="color: #000000"> Integer.valueOf(prefixLength);

         Length </span>= columnValue.length() < Length ?<span style="color: #000000"&gt; columnValue.length() : Length;
         </span><span style="color: #0000ff"&gt;int</span> sum = 0<span style="color: #000000"&gt;;
         </span><span style="color: #0000ff"&gt;for</span> (<span style="color: #0000ff"&gt;int</span> i = 0; i < Length; i++<span style="color: #000000"&gt;) {
             sum </span>= sum +<span style="color: #000000"&gt; columnValue.charAt(i);
         }
         Integer rst </span>= <span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;;
         </span><span style="color: #0000ff"&gt;for</span> (LongRange longRang : <span style="color: #0000ff"&gt;this</span><span style="color: #000000"&gt;.longRongs) {
             </span><span style="color: #0000ff"&gt;long</span> hash = sum %<span style="color: #000000"&gt; patternValue;
             </span><span style="color: #0000ff"&gt;if</span> (hash <= longRang.valueEnd &amp;&amp; hash >=<span style="color: #000000"&gt; longRang.valueStart) {
                 </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; longRang.nodeIndx;
             }
         }
         </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; rst;
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (NumberFormatException e){
         </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span> IllegalArgumentException(<span style="color: #0000ff"&gt;new</span> StringBuilder().append("columnValue:").append(columnValue).append(" Please eliminate any quote and non number within it."<span style="color: #000000"&gt;).toString(),e);
     }

    }

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">int<span style="color: #000000"> getPartitionNum() {
    <span style="color: #008000">//<span style="color: #008000"> int nPartition = this.longRongs.length;
    <span style="color: #008000">/*<span style="color: #008000">

    • fix #1284 这里的统计应该统计Range的nodeIndex的distinct总数
      <span style="color: #008000">*/<span style="color: #000000">
      Set distNodeIdxSet = <span style="color: #0000ff">new HashSet<span style="color: #000000">();
      <span style="color: #0000ff">for<span style="color: #000000">(LongRange range : longRongs) {
      distNodeIdxSet.add(range.nodeIndx);
      }
      <span style="color: #0000ff">int nPartition =<span style="color: #000000"> distNodeIdxSet.size();
      <span style="color: #0000ff">return<span style="color: #000000"> nPartition;
      }

    <span style="color: #0000ff">private <span style="color: #0000ff">void<span style="color: #000000"> initialize() {
    BufferedReader in = <span style="color: #0000ff">null<span style="color: #000000">;
    <span style="color: #0000ff">try<span style="color: #000000"> {
    <span style="color: #008000">//<span style="color: #008000"> FileInputStream fin = new FileInputStream(new File(fileMapPath));
    InputStream fin = <span style="color: #0000ff">this<span style="color: #000000">.getClass().getClassLoader()
    .getResourceAsStream(mapFile);
    <span style="color: #0000ff">if (fin == <span style="color: #0000ff">null<span style="color: #000000">) {
    <span style="color: #0000ff">throw <span style="color: #0000ff">new RuntimeException("can't find class resource file "
    +<span style="color: #000000"> mapFile);
    }
    in = <span style="color: #0000ff">new BufferedReader(<span style="color: #0000ff">new<span style="color: #000000"> InputStreamReader(fin));
    LinkedList longRangeList = <span style="color: #0000ff">new LinkedList<span style="color: #000000">();

         </span><span style="color: #0000ff"&gt;for</span> (String line = <span style="color: #0000ff"&gt;null</span>; (line = in.readLine()) != <span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;;) {
             line </span>=<span style="color: #000000"&gt; line.trim();
             </span><span style="color: #0000ff"&gt;if</span> (line.startsWith("#") || line.startsWith("//"<span style="color: #000000"&gt;)) {
                 </span><span style="color: #0000ff"&gt;continue</span><span style="color: #000000"&gt;;
             }
             </span><span style="color: #0000ff"&gt;int</span> ind = line.indexOf('='<span style="color: #000000"&gt;);
             </span><span style="color: #0000ff"&gt;if</span> (ind < 0<span style="color: #000000"&gt;) {
                 System.out.println(</span>" warn: bad line int " + mapFile + " :"
                         +<span style="color: #000000"&gt; line);
                 </span><span style="color: #0000ff"&gt;continue</span><span style="color: #000000"&gt;;
             }
                 String pairs[] </span>= line.substring(0,longEnd));
    
         }
         longRongs </span>= longRangeList.toArray(<span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; LongRange[longRangeList
                 .size()]);
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (Exception e) {
         </span><span style="color: #0000ff"&gt;if</span> (e <span style="color: #0000ff"&gt;instanceof</span><span style="color: #000000"&gt; RuntimeException) {
             </span><span style="color: #0000ff"&gt;throw</span><span style="color: #000000"&gt; (RuntimeException) e;
         } </span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt; {
             </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; RuntimeException(e);
         }
    
     } </span><span style="color: #0000ff"&gt;finally</span><span style="color: #000000"&gt; {
         </span><span style="color: #0000ff"&gt;try</span><span style="color: #000000"&gt; {
             in.close();
         } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (Exception e2) {
         }
     }

    }

    <span style="color: #0000ff">static <span style="color: #0000ff">class<span style="color: #000000"> LongRange {
    <span style="color: #0000ff">public <span style="color: #0000ff">final <span style="color: #0000ff">int<span style="color: #000000"> nodeIndx;
    <span style="color: #0000ff">public <span style="color: #0000ff">final <span style="color: #0000ff">long<span style="color: #000000"> valueStart;
    <span style="color: #0000ff">public <span style="color: #0000ff">final <span style="color: #0000ff">long<span style="color: #000000"> valueEnd;

     </span><span style="color: #0000ff"&gt;public</span> LongRange(<span style="color: #0000ff"&gt;int</span> nodeIndx,<span style="color: #0000ff"&gt;long</span><span style="color: #000000"&gt; valueEnd) {
         </span><span style="color: #0000ff"&gt;super</span><span style="color: #000000"&gt;();
         </span><span style="color: #0000ff"&gt;this</span>.nodeIndx =<span style="color: #000000"&gt; nodeIndx;
         </span><span style="color: #0000ff"&gt;this</span>.valueStart =<span style="color: #000000"&gt; valueStart;
         </span><span style="color: #0000ff"&gt;this</span>.valueEnd =<span style="color: #000000"&gt; valueEnd;
     }

    }
    }

    7.?冷热数据分片

    根据日期查询日志数据冷热数据分布 ,最近 n 个月的到实时交易库查询,超过 n 个月的按照 m 天分片

    在rule.xml里面的配置:

    create_time sharding-by-hotdate

    <span style="color: #0000ff"><<span style="color: #800000">function <span style="color: #ff0000">name<span style="color: #0000ff">="sharding-by-hotdate"<span style="color: #ff0000"> class<span style="color: #0000ff">="org.opencloudb.route.function.PartitionByHotDate"<span style="color: #0000ff">>
    <span style="color: #0000ff"><<span style="color: #800000">property <span style="color: #ff0000">name<span style="color: #0000ff">="dateFormat"<span style="color: #0000ff">>yyyy-MM-dd<span style="color: #0000ff"></<span style="color: #800000">property<span style="color: #0000ff">> <span style="color: #008000">
    <span style="color: #0000ff"><<span style="color: #800000">property <span style="color: #ff0000">name<span style="color: #0000ff">="sLastDay"<span style="color: #0000ff">>30<span style="color: #0000ff"></<span style="color: #800000">property<span style="color: #0000ff">> <span style="color: #008000">
    <span style="color: #0000ff"><<span style="color: #800000">property <span style="color: #ff0000">name<span style="color: #0000ff">="sPartionDay"<span style="color: #0000ff">>30<span style="color: #0000ff"></<span style="color: #800000">property<span style="color: #0000ff">> <span style="color: #008000">
    <span style="color: #0000ff"></<span style="color: #800000">function<span style="color: #0000ff">>

    对应代码:

<span style="color: #0000ff">import<span style="color: #000000"> java.text.ParseException;
<span style="color: #0000ff">import<span style="color: #000000"> java.text.SimpleDateFormat;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.Calendar;

<span style="color: #0000ff">import<span style="color: #000000"> org.slf4j.Logger;
<span style="color: #0000ff">import<span style="color: #000000"> org.slf4j.LoggerFactory;

<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.config.model.rule.RuleAlgorithm;

<span style="color: #008000">/**<span style="color: #008000">

  • 根据日期查询日志数据 冷热数据分布 ,最近n个月的到实时交易库查询,超过n个月的按照m天分片

  • <span style="color: #808080">@author<span style="color: #008000"> sw

  • <tableRule name="sharding-by-date">

    create_time sharding-by-hotdate PartitionByHotDate AbstractPartitionAlgorithm Logger LOGGER = LoggerFactory.getLogger(PartitionByHotDate.<span style="color: #0000ff">private<span style="color: #000000"> String dateFormat;
    <span style="color: #0000ff">private
    <span style="color: #000000"> String sLastDay;
    <span style="color: #0000ff">private
    <span style="color: #000000"> String sPartionDay;

    <span style="color: #0000ff">private <span style="color: #0000ff">long<span style="color: #000000"> sLastTime;
    <span style="color: #0000ff">private <span style="color: #0000ff">long<span style="color: #000000"> partionTime;
    <span style="color: #0000ff">private ThreadLocal<span style="color: #000000"> formatter;

    <span style="color: #0000ff">private <span style="color: #0000ff">long<span style="color: #000000"> beginDate;

    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">final <span style="color: #0000ff">long oneDay = 86400000<span style="color: #000000">;

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> init() {
    <span style="color: #0000ff">try<span style="color: #000000"> {
    formatter = <span style="color: #0000ff">new ThreadLocal<span style="color: #000000">() {
    @Override
    <span style="color: #0000ff">protected<span style="color: #000000"> SimpleDateFormat initialValue() {
    <span style="color: #0000ff">return <span style="color: #0000ff">new<span style="color: #000000"> SimpleDateFormat(dateFormat);
    }
    };
    sLastTime =<span style="color: #000000"> Integer.valueOf(sLastDay);
    partionTime = Integer.parseInt(sPartionDay) *<span style="color: #000000"> oneDay;
    } <span style="color: #0000ff">catch<span style="color: #000000"> (Exception e) {
    <span style="color: #0000ff">throw <span style="color: #0000ff">new<span style="color: #000000"> java.lang.IllegalArgumentException(e);
    }
    }

    @Override
    <span style="color: #0000ff">public<span style="color: #000000"> Integer calculate(String columnValue) {
    Integer targetPartition = -1<span style="color: #000000">;
    <span style="color: #0000ff">try<span style="color: #000000"> {
    <span style="color: #0000ff">long targetTime =<span style="color: #000000"> formatter.get().parse(columnValue).getTime();
    Calendar now =<span style="color: #000000"> Calendar.getInstance();
    <span style="color: #0000ff">long nowTime =<span style="color: #000000"> now.getTimeInMillis();

         beginDate </span>= nowTime - sLastTime *<span style="color: #000000"&gt; oneDay;
    
         </span><span style="color: #0000ff"&gt;long</span> diffDays = (nowTime - targetTime) / (1000 * 60 * 60 * 24) + 1<span style="color: #000000"&gt;;
         </span><span style="color: #0000ff"&gt;if</span>(diffDays-sLastTime <= 0 || diffDays<0<span style="color: #000000"&gt; ){
             targetPartition </span>= 0<span style="color: #000000"&gt;;
         }</span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt;{
             targetPartition </span>= (<span style="color: #0000ff"&gt;int</span>) ((beginDate - targetTime) / partionTime) + 1<span style="color: #000000"&gt;;
         }
    
         LOGGER.debug(</span>"PartitionByHotDate calculate for " + columnValue + " return " +<span style="color: #000000"&gt; targetPartition);
         </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; targetPartition;
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (ParseException e) {
         </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span> IllegalArgumentException(<span style="color: #0000ff"&gt;new</span> StringBuilder().append("columnValue:").append(columnValue).append(" Please check if the format satisfied."<span style="color: #000000"&gt;).toString(),String endValue)  {
     Integer[] targetPartition </span>= <span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;try</span><span style="color: #000000"&gt; {
         </span><span style="color: #0000ff"&gt;long</span> startTime =<span style="color: #000000"&gt; formatter.get().parse(beginValue).getTime();
         </span><span style="color: #0000ff"&gt;long</span> endTime =<span style="color: #000000"&gt; formatter.get().parse(endValue).getTime();
         Calendar now </span>=<span style="color: #000000"&gt; Calendar.getInstance();
         </span><span style="color: #0000ff"&gt;long</span> nowTime =<span style="color: #000000"&gt; now.getTimeInMillis();
    
         </span><span style="color: #0000ff"&gt;long</span> limitDate = nowTime - sLastTime *<span style="color: #000000"&gt; oneDay;
         </span><span style="color: #0000ff"&gt;long</span> diffDays = (nowTime - startTime) / (1000 * 60 * 60 * 24) + 1<span style="color: #000000"&gt;;
         </span><span style="color: #0000ff"&gt;if</span>(diffDays-sLastTime <= 0 || diffDays<0<span style="color: #000000"&gt; ){
             Integer [] re </span>= <span style="color: #0000ff"&gt;new</span> Integer[1<span style="color: #000000"&gt;];
             re[</span>0] = 0<span style="color: #000000"&gt;;
             targetPartition </span>=<span style="color: #000000"&gt; re ;
         }</span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt;{
             Integer [] re </span>= <span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;;
             Integer begin </span>= 0,end = 0<span style="color: #000000"&gt;;
             end </span>= <span style="color: #0000ff"&gt;this</span><span style="color: #000000"&gt;.calculate(beginValue);
             </span><span style="color: #0000ff"&gt;boolean</span> hasLimit = <span style="color: #0000ff"&gt;false</span><span style="color: #000000"&gt;;
             </span><span style="color: #0000ff"&gt;if</span>(endTime-limitDate > 0<span style="color: #000000"&gt;){
                 endTime </span>=<span style="color: #000000"&gt; limitDate;
                 hasLimit </span>= <span style="color: #0000ff"&gt;true</span><span style="color: #000000"&gt;;
             }
             begin </span>= <span style="color: #0000ff"&gt;this</span><span style="color: #000000"&gt;.calculate(formatter.get().format(endTime));
             </span><span style="color: #0000ff"&gt;if</span>(begin == <span style="color: #0000ff"&gt;null</span> || end == <span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;){
                 </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; re;
             }
             </span><span style="color: #0000ff"&gt;if</span> (end >=<span style="color: #000000"&gt; begin) {
                 </span><span style="color: #0000ff"&gt;int</span> len = end-begin+1<span style="color: #000000"&gt;;
                 </span><span style="color: #0000ff"&gt;if</span><span style="color: #000000"&gt;(hasLimit){
                     re </span>= <span style="color: #0000ff"&gt;new</span> Integer[len+1<span style="color: #000000"&gt;];
                     re[</span>0] = 0<span style="color: #000000"&gt;;
                     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span> i =0;i<len;i++<span style="color: #000000"&gt;){
                         re[i</span>+1]=begin+<span style="color: #000000"&gt;i;
                     }
                 }</span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt;{
                     re </span>= <span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; Integer[len];
                     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span> i=0;i<len;i++<span style="color: #000000"&gt;){
                         re[i]</span>=begin+<span style="color: #000000"&gt;i;
                     }
                 }
                 </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; re;
             }</span><span style="color: #0000ff"&gt;else</span><span style="color: #000000"&gt;{
                 </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; re;
             }
         }
     } </span><span style="color: #0000ff"&gt;catch</span><span style="color: #000000"&gt; (ParseException e) {
         </span><span style="color: #0000ff"&gt;throw</span> <span style="color: #0000ff"&gt;new</span> IllegalArgumentException(<span style="color: #0000ff"&gt;new</span> StringBuilder().append("endValue:").append(endValue).append(" Please check if the format satisfied."<span style="color: #000000"&gt;).toString(),e);
     }
     </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; targetPartition;

    }

    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setsPartionDay(String sPartionDay) {
    <span style="color: #0000ff">this.sPartionDay =<span style="color: #000000"> sPartionDay;
    }
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setDateFormat(String dateFormat) {
    <span style="color: #0000ff">this.dateFormat =<span style="color: #000000"> dateFormat;
    }
    <span style="color: #0000ff">public<span style="color: #000000"> String getsLastDay() {
    <span style="color: #0000ff">return<span style="color: #000000"> sLastDay;
    }
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> setsLastDay(String sLastDay) {
    <span style="color: #0000ff">this.sLastDay =<span style="color: #000000"> sLastDay;
    }
    }

    8.?一致性哈希分片

    1)首先求出mysql服务器(节点)的哈希值,并将其配置到0~2^32的圆(continuum)上。

    2)为每台mysql服务器物理节点虚拟出多个虚拟节点,并计算hash值映射到相同的圆上。

    3)然后从数据映射到的mysql服务器虚拟节点的位置开始顺时针查找,将数据保存到找到的第一个mysql服务器上。如果超过232仍然找不到服务器,就会保存到第一台mysql服务器上。

    ?

    特点:解决数据均匀分布

    在rule.xml里面的配置:

    id murmur 0 2 160 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西

    对应代码:

<span style="color: #0000ff">import<span style="color: #000000"> java.io.BufferedReader;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.ByteArrayInputStream;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.ByteArrayOutputStream;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.File;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.FileInputStream;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.FileNotFoundException;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.FileOutputStream;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.IOException;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.InputStream;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.InputStreamReader;
<span style="color: #0000ff">import<span style="color: #000000"> java.io.OutputStream;
<span style="color: #0000ff">import<span style="color: #000000"> java.nio.charset.Charset;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.ArrayList;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.HashMap;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.List;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.Map;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.Properties;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.SortedMap;
<span style="color: #0000ff">import<span style="color: #000000"> java.util.TreeMap;

<span style="color: #0000ff">import<span style="color: #000000"> com.google.common.hash.HashFunction;
<span style="color: #0000ff">import<span style="color: #000000"> com.google.common.hash.Hashing;

<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.config.model.rule.RuleAlgorithm;
<span style="color: #0000ff">import<span style="color: #000000"> io.mycat.util.exception.MurmurHashException;

<span style="color: #008000">/**<span style="color: #008000">

  • consistancy hash,murmur hash

  • implemented by Guava

  • <span style="color: #808080">@author<span style="color: #008000"> wuzhih

  • <span style="color: #008000">*/
    <span style="color: #0000ff">public <span style="color: #0000ff">class PartitionByMurmurHash <span style="color: #0000ff">extends AbstractPartitionAlgorithm <span style="color: #0000ff">implements<span style="color: #000000"> RuleAlgorithm {
    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">final <span style="color: #0000ff">int DEFAULT_VIRTUAL_BUCKET_TIMES=160<span style="color: #000000">;
    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">final <span style="color: #0000ff">int DEFAULT_WEIGHT=1<span style="color: #000000">;
    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">final Charset DEFAULT_CHARSET=Charset.forName("UTF-8"<span style="color: #000000">);

    <span style="color: #0000ff">private <span style="color: #0000ff">int<span style="color: #000000"> seed;
    <span style="color: #0000ff">private <span style="color: #0000ff">int<span style="color: #000000"> count;
    <span style="color: #0000ff">private <span style="color: #0000ff">int virtualBucketTimes=<span style="color: #000000">DEFAULT_VIRTUAL_BUCKET_TIMES;
    <span style="color: #0000ff">private Map<Integer,Integer> weightMap=<span style="color: #0000ff">new HashMap<><span style="color: #000000">();
    <span style="color: #008000">//<span style="color: #008000"> private String bucketMapPath;

    <span style="color: #0000ff">private<span style="color: #000000"> HashFunction hash;

    <span style="color: #0000ff">private SortedMap<Integer,Integer><span style="color: #000000"> bucketMap;
    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">void<span style="color: #000000"> init() {
    <span style="color: #0000ff">try<span style="color: #000000">{
    bucketMap=<span style="color: #0000ff">new TreeMap<><span style="color: #000000">();
    <span style="color: #008000">//<span style="color: #008000"> boolean serializableBucketMap=bucketMapPath!=null && bucketMapPath.length()>0;
    <span style="color: #008000">//<span style="color: #008000"> if(serializableBucketMap){
    <span style="color: #008000">//<span style="color: #008000"> File bucketMapFile=new File(bucketMapPath);
    <span style="color: #008000">//<span style="color: #008000"> if(bucketMapFile.exists() && bucketMapFile.length()>0){
    <span style="color: #008000">//<span style="color: #008000"> loadBucketMapFile();
    <span style="color: #008000">//<span style="color: #008000"> return;
    <span style="color: #008000">//<span style="color: #008000"> }
    <span style="color: #008000">//<span style="color: #008000"> }
    <span style="color: #000000"> generateBucketMap();
    <span style="color: #008000">//<span style="color: #008000"> if(serializableBucketMap){
    <span style="color: #008000">//<span style="color: #008000"> storeBucketMap();
    <span style="color: #008000">//<span style="color: #008000"> }
    }<span style="color: #0000ff">catch<span style="color: #000000">(Exception e){
    <span style="color: #0000ff">throw <span style="color: #0000ff">new<span style="color: #000000"> MurmurHashException(e);
    }
    }

    <span style="color: #0000ff">private <span style="color: #0000ff">void<span style="color: #000000"> generateBucketMap(){
    hash=Hashing.murmur3_32(seed);<span style="color: #008000">//<span style="color: #008000">计算一致性哈希的对象
    <span style="color: #0000ff">for(<span style="color: #0000ff">int i=0;i<count;i++){<span style="color: #008000">//<span style="color: #008000">构造一致性哈希环,用TreeMap表示
    StringBuilder hashName=<span style="color: #0000ff">new StringBuilder("SHARD-"<span style="color: #000000">).append(i);
    <span style="color: #0000ff">for(<span style="color: #0000ff">int n=0,shard=virtualBucketTimes*getWeight(i);n<shard;n++<span style="color: #000000">){
    bucketMap.put(hash.hashUnencodedChars(hashName.append("-NODE-"<span style="color: #000000">).append(n)).asInt(),i);
    }
    }
    weightMap=<span style="color: #0000ff">null<span style="color: #000000">;
    }
    <span style="color: #008000">//<span style="color: #008000"> private void storeBucketMap() throws IOException{
    <span style="color: #008000">//<span style="color: #008000"> try(OutputStream store=new FileOutputStream(bucketMapPath)){
    <span style="color: #008000">//<span style="color: #008000"> Properties props=new Properties();
    <span style="color: #008000">//<span style="color: #008000"> for(Map.Entry entry:bucketMap.entrySet()){
    <span style="color: #008000">//<span style="color: #008000"> props.setProperty(entry.getKey().toString(),entry.getValue().toString());
    <span style="color: #008000">//<span style="color: #008000"> }
    <span style="color: #008000">//<span style="color: #008000"> props.store(store,null);
    <span style="color: #008000">//<span style="color: #008000"> }
    <span style="color: #008000">//<span style="color: #008000"> }
    <span style="color: #008000">//<span style="color: #008000"> private void loadBucketMapFile() throws FileNotFoundException,IOException{
    <span style="color: #008000">//<span style="color: #008000"> try(InputStream in=new FileInputStream(bucketMapPath)){
    <span style="color: #008000">//<span style="color: #008000"> Properties props=new Properties();
    <span style="color: #008000">//<span style="color: #008000"> props.load(in);
    <span style="color: #008000">//<span style="color: #008000"> for(Map.Entry entry:props.entrySet()){
    <span style="color: #008000">//<span style="color: #008000"> bucketMap.put(Integer.parseInt(entry.getKey().toString()),Integer.parseInt(entry.getValue().toString()));
    <span style="color: #008000">//<span style="color: #008000"> }
    <span style="color: #008000">//<span style="color: #008000"> }
    <span style="color: #008000">//<span style="color: #008000"> }
    <span style="color: #008000">/**<span style="color: #008000">

    • 得到桶的权重,桶就是实际存储数据的DB实例
    • 从0开始的桶编号为key,权重为值,权重默认为1。
    • 键值必须都是整数
    • <span style="color: #808080">@param<span style="color: #008000"> bucket
    • <span style="color: #808080">@return
      <span style="color: #008000">*/
      <span style="color: #0000ff">private <span style="color: #0000ff">int getWeight(<span style="color: #0000ff">int<span style="color: #000000"> bucket){
      Integer w=<span style="color: #000000">weightMap.get(bucket);
      <span style="color: #0000ff">if(w==<span style="color: #0000ff">null<span style="color: #000000">){
      w=<span style="color: #000000">DEFAULT_WEIGHT;
      }
      <span style="color: #0000ff">return<span style="color: #000000"> w;
      }
      <span style="color: #008000">/**<span style="color: #008000">
    • 创建murmur_hash对象的种子,默认0
    • <span style="color: #808080">@param<span style="color: #008000"> seed
      <span style="color: #008000">*/
      <span style="color: #0000ff">public <span style="color: #0000ff">void setSeed(<span style="color: #0000ff">int<span style="color: #000000"> seed){
      <span style="color: #0000ff">this.seed=<span style="color: #000000">seed;
      }
      <span style="color: #008000">/**<span style="color: #008000">
    • 节点的数量
    • <span style="color: #808080">@param<span style="color: #008000"> count
      <span style="color: #008000">*/
      <span style="color: #0000ff">public <span style="color: #0000ff">void setCount(<span style="color: #0000ff">int<span style="color: #000000"> count) {
      <span style="color: #0000ff">this.count =<span style="color: #000000"> count;
      }
      <span style="color: #008000">/**<span style="color: #008000">
    • 虚拟节点倍数,virtualBucketTimes*count就是虚拟结点数量
    • <span style="color: #808080">@param<span style="color: #008000"> virtualBucketTimes
      <span style="color: #008000">*/
      <span style="color: #0000ff">public <span style="color: #0000ff">void setVirtualBucketTimes(<span style="color: #0000ff">int<span style="color: #000000"> virtualBucketTimes){
      <span style="color: #0000ff">this.virtualBucketTimes=<span style="color: #000000">virtualBucketTimes;
      }
      <span style="color: #008000">/**<span style="color: #008000">
    • 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。
    • 所有权重值必须是正整数,否则以1代替
    • <span style="color: #808080">@param<span style="color: #008000"> weightMapPath
    • <span style="color: #808080">@throws<span style="color: #008000"> IOException
    • <span style="color: #808080">@throws
      <span style="color: #008000">*/
      <span style="color: #0000ff">public <span style="color: #0000ff">void setWeightMapFile(String weightMapPath) <span style="color: #0000ff">throws<span style="color: #000000"> IOException{
      Properties props=<span style="color: #0000ff">new<span style="color: #000000"> Properties();
      <span style="color: #0000ff">try(BufferedReader reader=<span style="color: #0000ff">new BufferedReader(<span style="color: #0000ff">new InputStreamReader(<span style="color: #0000ff">this<span style="color: #000000">.getClass().getClassLoader().getResourceAsStream(weightMapPath),DEFAULT_CHARSET))){
      props.load(reader);
      <span style="color: #0000ff">for<span style="color: #000000">(Map.Entry entry:props.entrySet()){
      <span style="color: #0000ff">int weight=<span style="color: #000000">Integer.parseInt(entry.getValue().toString());
      weightMap.put(Integer.parseInt(entry.getKey().toString()),weight>0?weight:1<span style="color: #000000">);
      }
      }
      }
      <span style="color: #008000">//<span style="color: #008000"> /*
      <span style="color: #008000">//<span style="color: #008000">
      保存一致性hash的虚拟节点文件路径。
      <span style="color: #008000">//<span style="color: #008000"> 如果这个文件不存在或是空文件就按照指定的count,weightMapFile等构造新的MurmurHash数据结构并保存到这个路径的文件里。
      <span style="color: #008000">//<span style="color: #008000">
      如果这个文件已存在且不是空文件就加载这个文件里的内容作为MurmurHash数据结构,此时其它参数都忽略。
      <span style="color: #008000">//<span style="color: #008000"> 除第一次以外在之后增加节点时可以直接修改这个文件,不过不推荐这么做。如果节点数量变化了,推荐删除这个文件。
      <span style="color: #008000">//<span style="color: #008000">
      可以不指定这个路径,不指定路径时不会保存murmur hash
      <span style="color: #008000">//<span style="color: #008000"> @param bucketMapPath
      <span style="color: #008000">//<span style="color: #008000">
      /
      <span style="color: #008000">//<span style="color: #008000"> public void setBucketMapPath(String bucketMapPath){
      <span style="color: #008000">//<span style="color: #008000"> this.bucketMapPath=bucketMapPath;
      <span style="color: #008000">//<span style="color: #008000"> }
      <span style="color: #000000"> @Override
      <span style="color: #0000ff">public<span style="color: #000000"> Integer calculate(String columnValue) {
      SortedMap<Integer,Integer> tail =<span style="color: #000000"> bucketMap.tailMap(hash.hashUnencodedChars(columnValue).asInt());
      <span style="color: #0000ff">if<span style="color: #000000"> (tail.isEmpty()) {
      <span style="color: #0000ff">return<span style="color: #000000"> bucketMap.get(bucketMap.firstKey());
      }
      <span style="color: #0000ff">return<span style="color: #000000"> tail.get(tail.firstKey());
      }

    @Override
    <span style="color: #0000ff">public <span style="color: #0000ff">int<span style="color: #000000"> getPartitionNum() {
    <span style="color: #0000ff">int nPartition = <span style="color: #0000ff">this<span style="color: #000000">.count;
    <span style="color: #0000ff">return<span style="color: #000000"> nPartition;
    }

    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">void hashTest() <span style="color: #0000ff">throws<span style="color: #000000"> IOException{
    PartitionByMurmurHash hash=<span style="color: #0000ff">new<span style="color: #000000"> PartitionByMurmurHash();
    hash.count=10;<span style="color: #008000">//<span style="color: #008000">分片数
    <span style="color: #000000"> hash.init();

     </span><span style="color: #0000ff"&gt;int</span>[] bucket=<span style="color: #0000ff"&gt;new</span> <span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt;[hash.count];
    
     Map</span><Integer,List<Integer>> hashed=<span style="color: #0000ff"&gt;new</span> HashMap<><span style="color: #000000"&gt;();
    
     </span><span style="color: #0000ff"&gt;int</span> total=1000_0000;<span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;数据量</span>
     <span style="color: #0000ff"&gt;int</span> c=0<span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span> i=100_0000;i<total+100_0000;i++){<span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;假设分片键从100万开始</span>
         c++<span style="color: #000000"&gt;;
         </span><span style="color: #0000ff"&gt;int</span> h=<span style="color: #000000"&gt;hash.calculate(Integer.toString(i));
         bucket[h]</span>++<span style="color: #000000"&gt;;
         List</span><Integer> list=<span style="color: #000000"&gt;hashed.get(h);
         </span><span style="color: #0000ff"&gt;if</span>(list==<span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;){
             list</span>=<span style="color: #0000ff"&gt;new</span> ArrayList<><span style="color: #000000"&gt;();
             hashed.put(h,list);
         }
         list.add(i);
     }
     System.out.println(c</span>+"   "+<span style="color: #000000"&gt;total);
     </span><span style="color: #0000ff"&gt;double</span> d=0<span style="color: #000000"&gt;;
     c</span>=0<span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;int</span> idx=0<span style="color: #000000"&gt;;
     System.out.println(</span>"index    bucket   ratio"<span style="color: #000000"&gt;);
     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt; i:bucket){
         d</span>+=i/(<span style="color: #0000ff"&gt;double</span><span style="color: #000000"&gt;)total;
         c</span>+=<span style="color: #000000"&gt;i;
         System.out.println(idx</span>+++"  "+i+"   "+(i/(<span style="color: #0000ff"&gt;double</span><span style="color: #000000"&gt;)total));
     }
     System.out.println(d</span>+"  "+<span style="color: #000000"&gt;c);
    
     Properties props</span>=<span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; Properties();
     </span><span style="color: #0000ff"&gt;for</span><span style="color: #000000"&gt;(Map.Entry entry:hash.bucketMap.entrySet()){
         props.setProperty(entry.getKey().toString(),entry.getValue().toString());
     }
     ByteArrayOutputStream out</span>=<span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; ByteArrayOutputStream();
     props.store(out,</span><span style="color: #0000ff"&gt;null</span><span style="color: #000000"&gt;);
    
     props.clear();
     props.load(</span><span style="color: #0000ff"&gt;new</span><span style="color: #000000"&gt; ByteArrayInputStream(out.toByteArray()));
     System.out.println(props);
     System.out.println(</span>"****************************************************"<span style="color: #000000"&gt;);

    <span style="color: #008000">//<span style="color: #008000"> rehashTest(hashed.get(0));
    <span style="color: #000000"> }
    <span style="color: #0000ff">private <span style="color: #0000ff">static <span style="color: #0000ff">void rehashTest(List<span style="color: #000000"> partition){
    PartitionByMurmurHash hash=<span style="color: #0000ff">new<span style="color: #000000"> PartitionByMurmurHash();
    hash.count=12;<span style="color: #008000">//<span style="color: #008000">分片数
    <span style="color: #000000"> hash.init();

     </span><span style="color: #0000ff"&gt;int</span>[] bucket=<span style="color: #0000ff"&gt;new</span> <span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt;[hash.count];
    
     </span><span style="color: #0000ff"&gt;int</span> total=partition.size();<span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;数据量</span>
     <span style="color: #0000ff"&gt;int</span> c=0<span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span> i:partition){<span style="color: #008000"&gt;//</span><span style="color: #008000"&gt;假设分片键从100万开始</span>
         c++<span style="color: #000000"&gt;;
         </span><span style="color: #0000ff"&gt;int</span> h=<span style="color: #000000"&gt;hash.calculate(Integer.toString(i));
         bucket[h]</span>++<span style="color: #000000"&gt;;
     }
     System.out.println(c</span>+"   "+<span style="color: #000000"&gt;total);
     c</span>=0<span style="color: #000000"&gt;;
     </span><span style="color: #0000ff"&gt;int</span> idx=0<span style="color: #000000"&gt;;
     System.out.println(</span>"index    bucket   ratio"<span style="color: #000000"&gt;);
     </span><span style="color: #0000ff"&gt;for</span>(<span style="color: #0000ff"&gt;int</span><span style="color: #000000"&gt; i:bucket){
         c</span>+=<span style="color: #000000"&gt;i;
         System.out.println(idx</span>+++"  "+i+"   "+(i/(<span style="color: #0000ff"&gt;double</span><span style="color: #000000"&gt;)total));
     }

    }
    <span style="color: #0000ff">public <span style="color: #0000ff">static <span style="color: #0000ff">void main(String[] args) <span style="color: #0000ff">throws<span style="color: #000000"> IOException {
    hashTest();
    }
    }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读