使用mycat分表(一致性hash)

来源:互联网 发布:linux mysql 导入dump 编辑:程序博客网 时间:2024/06/06 19:57

业务介绍

我们有一个横向分表的业务,本来是想自己搞的,但也想尝试下一些中间件,找到了mycat先试下,
现在是2017/12 , 版本采用 mycat1.6.5

安装及相关内容
https://github.com/MyCATApache/Mycat-Server

mysql准备

创建三个db :db1,db2,db3,都加入这张表:

CREATE TABLE `travelrecord` (  `id` bigint(20) NOT NULL,  `user_id` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,  `traveldate` date DEFAULT NULL,  `fee` decimal(10,0) DEFAULT NULL,  `days` int(11) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

相关配置

cd /alidata/server/mycat/mycat

基本上默认配置 加下小修改就行了,主要是server.xml 和 scheme.xml
server.xml:

    <property name="serverPort">4566</property>    <property name="managerPort">4567</property>      <firewall>       <whitehost>          <host host="*" user="abcefg"/>       </whitehost>       <blacklist check="false">       </blacklist>    </firewall>    <user name="abcefg">            <property name="password">abcefg2017</property>            <property name="schemas">TESTDB</property>    </user>

scheme.xml
按照官网的默认配置修改了下,简单配置:

<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://io.mycat/">;        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">                <!-- auto sharding by id (long) -->                <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />        </schema>        <dataNode name="dn1" dataHost="localhost1" database="db1" />        <dataNode name="dn2" dataHost="localhost1" database="db2" />        <dataNode name="dn3" dataHost="localhost1" database="db3" />        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">                <heartbeat>select user()</heartbeat>                <writeHost host="hostS1" url="127.0.0.1:3306" user="mycat"                                   password="mycat123" />        </dataHost>      </mycat:schema>

如果你的内存不太够,记得改一下 wrapper.conf 里面的内存配置,

mycat的服务(用mysql客户端访问):xxxx 端口 4566 , 用户xxx,密码 xxx2017

实际数据库表地址: xxx 端口 3306 用户mycat 密码 mycat123 (里面的dn1,dn2,dn3)

启动

/xxx/mycat/mycat/bin/mycat start
/xxx/mycat/mycat/bin/mycat stop

mycat 的一些策略

mycat的分片规则有很多,可能参考 其文档http://www.mycat.io/document/Mycat_V1.6.0.pdf
这里写图片描述

具体在规则配置上,则是rule.xml中
以下为我取的一个 一致性hash的配置

<function name="murmur"                class="io.mycat.route.function.PartitionByMurmurHash">                <property name="seed">0</property><!-- 默认是0 -->                <property name="count">4</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->                <property name="virtualBucketTimes">160</property><!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍 -->                <!-- <property name="weightMapFile">weightMapFile</property> 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 -->        </function>

如果要使用,建立一个tableRule,algorithm 引用这个murmur

        <tableRule name="rule-guid">                <rule>                        <columns>device_guid</columns>                        <algorithm>murmur</algorithm>                </rule>        </tableRule>

在表映射中的scheme.xml中,则这样引用

<table name="tx_device_user_jiguang" primaryKey="device_guid" subTables="tx_device_user_jiguang0$0-3" dataNode="dn1" rule="rule-guid" />

一致性hash的分析

我们要使用其一致性hash,但不知道其具体的规则,于是找他们的源码以确认,源码可在其github中找
PartitionByMurmurHash.java
发现这个类的init的时候调用生成bucketMap,

private void generateBucketMap(){    hash=Hashing.murmur3_32(seed);//计算一致性哈希的对象    for(int i=0;i<count;i++){//构造一致性哈希环,用TreeMap表示        StringBuilder hashName=new StringBuilder("SHARD-").append(i);        for(int n=0,shard=virtualBucketTimes*getWeight(i);n<shard;n++){            bucketMap.put(hash.hashUnencodedChars(hashName.append("-NODE-").append(n)).asInt(),i);        }    }    weightMap=null;}

在其使用的时候则用

public Integer calculate(String columnValue) {    SortedMap<Integer, Integer> tail = bucketMap.tailMap(hash.hashUnencodedChars(columnValue).asInt());    if (tail.isEmpty()) {        return bucketMap.get(bucketMap.firstKey());    }    return tail.get(tail.firstKey());}

结合 一致性hash的逻辑,可以确认,generateBucketMap是 生成一个主机数*160(160是默认值)的treeMap,其val为主机序列,而calculate的方法,入参为 字段值,出参则为 主机序列.

提示,网上很多说的bucketMapPath 这个rule.xml 的配置在这里没作用, 看源代码,貌似被注释了。。。

原创粉丝点击