Mycat-配置详解

Mark笔记:

schema.xml

Schema.xml 作为MyCat 中重要的配置文件之一,管理着MyCat 的逻辑库、表、分片规则、DataNode 以及DataSource。弄懂这些配置,是正确使用MyCat 的前提。

schema 标签

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"></schema>

schema 标签用于定义MyCat 实例中的逻辑库,MyCat 可以有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用schema 标签来划分这些不同的逻辑库。

如果不配置schema 标签,所有的表配置,会属于同一个默认的逻辑库。

 

如上所示的配置就配置了两个不同的逻辑库,逻辑库的概念和MYSQL 数据库中Database 的概念相同,我们在查询这两个不同的逻辑库中表的时候需要切换到该逻辑库下才可以查询到所需要的表。

schema 标签的相关属性:

 

dataNode

该属性用于绑定逻辑库到某个具体的database 上,具体如下配置:

<schema name="USERDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn2">

<!—配置需要分片的表-->

<table name=“tuser” dataNode=”dn1”/>

</schema>

那么现在tuser 就绑定到dn1 所配置的具体database 上,可以直接访问这个database,没有配置的表则会走默认节点dn2,这里注意没有配置在分片里面的表工具查看无法显示,但是可以正常使用。

checkSQLschema

当该值设置为true 时,如果我们执行语句select * from TESTDB.travelrecord;则MyCat 会把语句修改为select * from travelrecord;。即把表示schema 的字符去掉,避免发送到后端数据库执行时报错。

不过,即使设置该值为true ,如果语句所带的是并非是schema 指定的名字,例如:**select * from db1.travelrecord;** 那么MyCat 并不会删除db1 这个字段,如果没有定义该库的话则会报错,所以在提供SQL语句的最好是不带这个字段。

sqlMaxLimit

当该值设置为某个数值时。每条执行的SQL 语句,如果没有加上limit 语句,MyCat 也会自动的加上所对应的值。例如设置值为100,执行**select * from TESTDB.travelrecord;**的效果为和执行**select * from TESTDB.travelrecord limit 100;**相同。

不设置该值的话,MyCat 默认会把查询到的信息全部都展示出来,造成过多的输出。所以,在正常使用中,还是建议加上一个值,用于减少过多的数据返回。

当然SQL 语句中也显式的指定limit 的大小,不受该属性的约束。

table 标签

Table 标签定义了MyCat 中的逻辑表,所有需要拆分的表都需要在这个标签中定义。

table 标签的相关属性:

 

name 属性

定义逻辑表的表名,这个名字就如同我们在数据库中执行create table 命令指定的名字一样,同个schema 标签中定义的名字必须唯一。

dataNode 属性

定义这个逻辑表所属的dataNode, 该属性的值需要和dataNode 标签中name 属性的值相互对应。如果需要定义的dn 过多可以使用如下的方法减少配置:

 

rule 属性

该属性用于指定逻辑表要使用的规则名字,规则名字在rule.xml 中定义,必须与tableRule 标签中name 属性属性值一一对应。

ruleRequired 属性

该属性用于指定表是否绑定分片规则,如果配置为true,但没有配置具体rule 的话,程序会报错。

primaryKey 属性

该逻辑表对应真实表的主键,例如:分片的规则是使用非主键进行分片的,那么在使用主键查询的时候,就会发送查询语句到所有配置的DN 上,如果使用该属性配置真实表的主键。难么MyCat 会缓存主键与具体DN 的信息,那么再次使用非主键进行查询的时候就不会进行广播式的查询,就会直接发送语句给具体的DN,但是尽管配置该属性,如果缓存并没有命中的话,还是会发送语句给具体的DN,来获得数据。

type 属性

该属性定义了逻辑表的类型,目前逻辑表只有“全局表”和”普通表”两种类型。对应的配置:

 全局表:global。

 普通表:不指定该值为globla 的所有表。

autoIncrement 属性

mysql 对非自增长主键,使用last_insert_id()是不会返回结果的,只会返回0。所以,只有定义了自增长主键的表才可以用last_insert_id()返回主键值。

mycat 目前提供了自增长主键功能,但是如果对应的mysql 节点上数据表,没有定义auto_increment,那么在mycat 层调用last_insert_id()也是不会返回结果的。

由于insert 操作的时候没有带入分片键,mycat 会先取下这个表对应的全局序列,然后赋值给分片键。这样才能正常的插入到数据库中,最后使用last_insert_id()才会返回插入的分片键值。如果要使用这个功能最好配合使用数据库模式的全局序列。

使用autoIncrement=“true” 指定这个表有使用自增长主键,这样mycat 才会不抛出分片键找不到的异常。

使用autoIncrement=“false” 来禁用这个功能,当然你也可以直接删除掉这个属性。默认就是禁用的。

subTables

使用方式添加subTables="t_order$1-2,t_order3"。

目前分表1.6 以后开始支持并且dataNode 在分表条件下只能配置一个,分表条件下不支持各种条件的join 语句。

needAddLimit 属性

指定表是否需要自动的在每个语句后面加上limit 限制。由于使用了分库分表,数据量有时会特别巨大。这时候执行查询语句,如果恰巧又忘记了加上数量限制的话。那么查询所有的数据出来,也够等上一小会儿的。

所以,mycat 就自动的为我们加上LIMIT 100。当然,如果语句中有limit,就不会在次添加了。这个属性默认为true,你也可以设置成false禁用掉默认行为。

childTable 标签

childTable 标签用于定义E-R 分片的子表。通过标签上的属性与父表进行关联。

childTable 标签的相关属性:

 

name 属性

定义子表的表名。

joinKey 属性

插入子表的时候会使用这个列的值查找父表存储的数据节点。

parentKey 属性

属性指定的值一般为与父表建立关联关系的列名。程序首先获取joinkey 的值,再通过parentKey 属性指定的列名产生查询语句,通过执行该语句得到父表存储在哪个分片上。从而确定子表存储的位置。

primaryKey 属性

同table 标签所描述的。

needAddLimit 属性

同table 标签所描述的。

dataNode 标签

<dataNode name="dn1" dataHost="lch3307" database="db1" ></dataNode>

dataNode 标签定义了MyCat 中的数据节点,也就是我们通常说所的数据分片。一个dataNode 标签就是一个独立的数据分片。

例子中所表述的意思为:使用名字为lch3307 数据库实例上的db1 物理数据库,这就组成一个数据分片,最后,我们使用名字dn1 标识这个分片。

dataNode 标签的相关属性:

 

name 属性

定义数据节点的名字,这个名字需要是唯一的,我们需要在table 标签上应用这个名字,来建立表与分片对应的关系。

dataHost 属性

该属性用于定义该分片属于哪个数据库实例的,属性值是引用dataHost 标签上定义的name 属性。

database 属性

该属性用于定义该分片属性哪个具体数据库实例上的具体库,因为这里使用两个纬度来定义分片,就是:实例+具体的库。因为每个库上建立的表和表结构是一样的。所以这样做就可以轻松的对表进行水平拆分。

dataHost 标签

作为Schema.xml 中最后的一个标签,该标签在mycat 逻辑库中也是作为最底层的标签存在,直接定义了具体的数据库实例、读写分离配置和心跳语句。

dataHost 标签的相关属性:

 

name 属性

唯一标识dataHost 标签,供上层的标签使用。

maxCon 属性

指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost、readHost 标签都会使用这个属性的值来实例化出连接池的最大连接数。

minCon 属性

指定每个读写实例连接池的最小连接,初始化连接池的大小。

balance 属性

负载均衡类型,目前的取值有:

1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost 上。

2. balance="1",全部的readHost 与stand by writeHost 参与select 语句的负载均衡,简单的说,当双

主双从模式(M1->S1,M2->S2,并且M1 与M2 互为主备),正常情况下,M2,S1,S2 都参与select 语句的负载均衡。

3. balance="2",所有读操作都随机的在writeHost、readhost 上分发。

4. balance="3",所有读请求随机的分发到wiriterHost 对应的readhost 执行,writerHost 不负担读压力,注意balance=3 只在1.4 及其以后版本有。

writeType 属性

负载均衡类型,目前的取值有2种:

1. writeType="0", 所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .

2. writeType="1",所有写操作都随机的发送到配置的writeHost,1.5 以后废弃不推荐。

dbType 属性

指定后端连接的数据库类型,目前支持二进制的mysql 协议,还有其他使用JDBC 连接的数据库。例如:mongodb、oracle、spark 等。

dbDriver 属性

指定连接后端数据库使用的Driver,目前可选的值有native 和JDBC。使用native 的话,因为这个值执行的是二进制的mysql 协议,所以可以使用mysql 和maridb。其他类型的数据库则需要使用JDBC 驱动来支持。

从1.6 版本开始支持postgresql 的native 原始协议。

如果使用JDBC 的话需要将符合JDBC 4 标准的驱动JAR 包放到MYCAT\lib 目录下,并检查驱动JAR 包中包括如下目录结构的文件:META-INF\services\java.sql.Driver。在这个文件内写上具体的Driver 类名,例如:

com.mysql.jdbc.Driver。

switchType 属性

-1 表示不自动切换

1 默认值,自动切换

2 基于MySQL 主从同步的状态决定是否切换

心跳语句为show slave status

3 基于MySQL galary cluster 的切换机制(适合集群)(1.4.1)

心跳语句为show status like ‘wsrep%’

slaveThreshold属性

Mycat 心跳机制通过检测show slave status 中的"Seconds_Behind_Master", "Slave_IO_Running","Slave_SQL_Running" 三个字段来确定当前主从同步的状态以及Seconds_Behind_Master 主从复制时延,当Seconds_Behind_Master>slaveThreshold 时,读写分离筛选器会过滤掉此Slave 机器,防止读到很久之前的旧数据。

heartbeat 标签

这个标签内指明用于和后端数据库进行心跳检查的语句。例如,MYSQL 可以使用select user(),Oracle 可以使用select 1 from dual 等。

这个标签还有一个connectionInitSql 属性,主要是当使用Oracla 数据库时,需要执行的初始化SQL 语句就这个放到这里面来。例如:alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'

7.7.1 writeHost 标签、readHost 标签

这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端连接池。唯一不同的是,writeHost 指定写实例、readHost 指定读实例,组着这些读写实例来满足系统的要求。

在一个dataHost 内可以定义多个writeHost 和readHost。但是,如果writeHost 指定的后端数据库宕机,那么这个writeHost 绑定的所有readHost 都将不可用。另一方面,由于这个writeHost 宕机系统会自动的检测到,并切换到备用的writeHost 上去。

这两个标签的属性相同

 

host 属性

用于标识不同实例,一般writeHost 我们使用*M1,readHost 我们用*S1。

url 属性

后端实例连接地址,如果是使用native 的dbDriver,则一般为address:port 这种形式。用JDBC 或其他的

dbDriver,则需要特殊指定。当使用JDBC 时则可以这么写:jdbc:mysql://localhost:3306/。

user 属性

后端存储实例需要的用户名字。

password 属性

后端存储实例需要的密码。

weight 属性

权重配置在readhost 中作为读节点的权重(1.4 以后)。

usingDecrypt 属性

是否对密码加密默认0 否如需要开启配置1,同时使用加密程序对密码加密,加密命令为:

执行mycat jar 程序(1.4.1 以后):

java -cp Mycat-server-1.4.1-dev.jar io.mycat.util.DecryptUtil 1:host:user:password

Mycat-server-1.4.1-dev.jar 为mycat download 下载目录的jar

1:host:user:password 中1 为db 端加密标志,host 为dataHost 的host 名称

server.xml

server.xml 几乎保存了所有mycat 需要的系统配置信息

user 标签

<user name="test">

<property name="password">test</property>

<property name="schemas">TESTDB</property>

<property name="readOnly">true</property>

<property name="benchmark">11111</property>

<privileges check="false">

<schema name="TESTDB" dml="0010" showTables="custome/mysql">

<table name="tbl_user" dml="0110"></table>

<table name="tbl_dynamic" dml="1111"></table>

</schema>

</privileges>

</user>

主要用于定义登录mycat 的用户和权限。例如上面的例子中,我定义了一个用户,用户名为test、密码也为test,可访问的schema 也只有TESTDB 一个。

如果我在schema.xml 中定义了多个schema,那么这个用户是无法访问其他的schema。

嵌套的property 标签则是具体声明的属性值

Benchmark 属性

Benchmark:mycat 连接服务降级处理:

benchmark 基准, 当前端的整体connection 数达到基准值时, 对来自该账户的请求开始拒绝连接,0 或不设表示不限制例如<property name="benchmark">1000</property>

privileges 子节点

对用户的schema 及下级的table 进行精细化的DML 权限控制,privileges 节点中的check 属性是用于标识是否开启DML 权限检查, 默认false 标识不检查,当然privileges 节点不配置,等同check=false,

由于Mycat 一个用户的schemas 属性可配置多个schema ,所以privileges 的下级节点schema 节点同样可配置多个,对多库多表进行细粒度的DML 权限控制

 

system 标签

charset 属性

字符集设置。

processors 属性

这个属性主要用于指定系统可用的线程数,默认值为机器CPU 核心线程数。

processorBufferChunk 属性

这个属性指定每次分配Socket Direct Buffer 的大小,默认是4096 个字节。这个属性也影响buffer pool 的长度。如果一次性获取的数过大buffer 不够用经常出现警告,则可以适当调大。

processorExecutor 属性

这个属性主要用于指定NIOProcessor 上共享的businessExecutor 固定线程池大小。mycat 在需要处理一些异步逻辑的时候会把任务提交到这个线程池中。新版本中这个连接池的使用频率不是很大了,可以设置一个较小的值。

sequnceHandlerType 属性

指定使用Mycat 全局序列的类型。0 为本地文件方式,1 为数据库方式,2 为时间戳序列方式,3 为分布式ZK ID 生成器,4 为zk 递增id 生成。

从1.6 增加两种ZK 的全局ID 生成算法。

Mysql 连接相关属性

初始化mysql 前后端连接所涉及到的一些属性:

idleTimeout : 指定连接的空闲超时时间。某连接在发起空闲检查下,发现距离上次使用超过了空闲时间,那么这个连接会被回收,就是被直接的关闭掉。默认30 分钟,单位毫秒。

服务相关属性

这里介绍一个与服务相关的属性,主要会影响外部系统对mycat 的感知。

bindIp : mycat 服务监听的IP 地址,默认值为0.0.0.0。

serverPort : 定义mycat 的使用端口,默认值为8066。

managerPort : 定义mycat 的管理端口,默认值为9066。

fakeMySQLVersion

mycat 模拟的mysql 版本号,默认值为5.6 版本,如非特需,不要修改这个值,目前支持设置5.5,5.6 版本,其他版本可能会有问题。

此特性从1.6 版本开始支持。

全局表一致性检测

<property name="useGlobleTableCheck">0</property> <!-- 1 为开启全加班一致性检测、0 为关闭-->

原理通过在全局表增加_MYCAT_OP_TIME 字段来进行一致性检测,类型为bigint,create 语句通过mycat执行会自动加上这个字段,其他情况请自己手工添加。

此特性从1.6 版本开始支持。

分布式事务开关

<!--分布式事务开关,0 为不过滤分布式事务,1 为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2 为不过滤分布式事务,但是记录分布式事务日志-->

<property name="handleDistributedTransactions">0</property>

主要应用场景,主要为了控制是否允许跨库事务。

此特性从1.6 版本开始支持。

Off Heap for Mycat

此特性从1.6 版本开始支持。

<property name="useOffHeapForMerge">1</property>

1.使用非堆内存(Direct Memory)处理跨分片结果集的Merge/order by/group by/limit。

2.通过server.xml 中的useOffHeapForMerge 参数配置是否启用非堆内存处理跨分片结果集

3.Mycat 内存分层管理:

a.结果集处理内存;

b.系统预留内存;

c.网络处理内存共三块。

其中网络处理内存部分全部为Direct Memory,结果集内存分为Direct Memory 和HeapMemory。但目前仅使用Direct Memory。系统预留内存为On Heap Memory。

rule.xml

rule.xml 里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有tableRule 和function 这两个标签。在具体使用过程中可以按照需求添加tableRule 和function。

tableRule 标签

这个标签定义表规则。

定义的表规则,在schema.xml:

<tableRule name="rule1">

<rule>

<columns>id</columns>

<algorithm>func1</algorithm>

</rule>

</tableRule>

name 属性指定唯一的名字,用于标识不同的表规则。

内嵌的rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。

columns 内指定要拆分的列名字。

algorithm 使用function 标签中的name 属性。连接表规则和具体路由算法。当然,多个表规则可以连接到同一个路由算法上。table 标签内使用。让逻辑表使用这个规则进行分片。

function 标签

<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">

<property name="mapFile">partition-hash-int.txt</property>

</function>

name 指定算法的名字。

class 制定路由算法具体的类名字。

property 为具体算法需要用到的一些属性。

Mycat分片规则

在数据切分处理中,特别是水平切分中,中间件最终要的两个处理过程就是数据的切分、数据的聚合。选择合适的切分规则,至关重要,因为它决定了后续数据聚合的难易程度,甚至可以避免跨库的数据聚合处理。

前面讲了数据切分中重要的几条原则,其中有几条是数据冗余,表分组(Table Group),这都是业务上规避跨库join 的很好的方式,但不是所有的业务场景都适合这样的规则,

主键分片vs 非主键分片

当没有任何字段可以作为分片字段的时候,主键分片就是唯一选择,其优点是按照主键的查询最快。

若有某个合适的业务字段比较合适作为分片字段,则建议采用此业务字段分片,选择分片字段的条件如下:

 尽可能的比较均匀分布数据到各个节点上;

 该业务字段是最频繁的或者最重要的查询条件。

常见的除了主键之外的其他可能分片字段有“订单创建时间”、“店铺类别”或“所在省”等。

选择合适分片的规则,尽量规避跨库Join 是一条最重要的原则,每种规则都有特定的场景,分析每种规则去选择合适的应用到项目中。

分片枚举

通过在配置文件中配置可能的枚举id,自己配置分片,本规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国省份区县固定的,这类业务使用本条规则,配置如下:

<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">

<property name="mapFile">partition-hash-int.txt</property>

<property name="type">0</property>

<property name="defaultNode">0</property>

</function>

partition-hash-int.txt 配置:

10000=0

10010=1

DEFAULT_NODE=1

上面columns 标识将要分片的表字段,algorithm 分片函数,

其中分片函数配置中,mapFile 标识配置文件名称,type 默认值为0,0 表示Integer,非零表示String,

所有的节点配置都是从0 开始,及0 代表节点1

 defaultNode 默认节点:小于0 表示不设置默认节点,大于等于0 表示设置默认节点 默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点, 如果不配置默认节点(defaultNode 值小于0 表示不配置默认节点),碰到 不识别的枚举值就会报错, can’t find datanode for sharding column:column_name val:ffffffff

固定分片hash 算法

本条规则类似于十进制的求模运算,区别在于是二进制的操作,是取id 的二进制低10 位,即id 二进制&1111111111。

<function name="func1" class="io.mycat.route.function.PartitionByLong">

<property name="partitionCount">2,1</property>

<property name="partitionLength">256,512</property>

</function>

配置说明:

上面columns 标识将要分片的表字段,algorithm 分片函数,partitionCount 分片个数列表,partitionLength 分片范围列表

分区长度:最大支持1024个 分区

约束:

count,length 两个数组的长度必须是一致的。

1024 = sum((count[i]*length[i])). count 和length 两个向量的点积恒等于1024

用法例子:

本例的分区策略:希望将数据水平分成3 份,前两份各占25%,第三份占50%。(故本例非均匀分区)

 |<———————1024———————————>|

 |<—-256—>|<—-256—>|<———-512————->|

 | partition0 | partition1 | partition2 |

  0 -------255,256------511,512----1023

如果需要平均分配设置:平均分为4 分片,partitionCount*partitionLength=1024

<function name="func1" class="io.mycat.route.function.PartitionByLong">

<property name="partitionCount">4</property>

<property name="partitionLength">256</property>

</function>

范围约定

此分片适用于,提前规划好分片字段某个范围属于哪个分片,

start <= range <= end.

range start-end ,data node index

K=1000,M=10000.

<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">

<property name="mapFile">autopartition-long.txt</property>

<property name="defaultNode">0</property>

</function>

配置说明:

上面columns 标识将要分片的表字段,algorithm 分片函数,

rang-long 函数中mapFile 代表配置文件路径

defaultNode 超过范围后的默认节点。

所有的节点配置都是从0 开始,及0 代表节点1,此配置非常简单,即预先制定可能的id 范围到某个分片

0-500M=0

500M-1000M=1

1000M-1500M=2

0-10000000=0

10000001-20000000=1

取模

此规则为对分片字段求摸运算。

<function name="mod-long" class="io.mycat.route.function.PartitionByMod">

<property name="count">3</property>

</function>

配置说明:

此种配置非常明确即根据id 进行十进制求模运算。

按日期(天)分片

此规则为按天分片。

<function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate">

<property name="dateFormat">yyyy-MM-dd</property>

<property name="sBeginDate">2014-01-01</property>

<property name="sEndDate">2014-01-02</property>

<property name="sPartionDay">10</property>

</function>

配置说明:

dateFormat :日期格式

sBeginDate :开始日期

sEndDate:结束日期

sPartionDay :分区天数,即默认从开始日期算起,分隔10 天一个分区

如果配置了sEndDate 则代表数据达到了这个日期的分片后后循环从开始分片插入。

取模范围约束

此种规则是取模运算与范围约束的结合。

<function name="sharding-by-pattern" class="io.mycat.route.function.PartitionByPattern">

<property name="patternValue">256</property>

<property name="defaultNode">2</property>

<property name="mapFile">partition-pattern.txt</property>

</function>

partition-pattern.txt

# id partition range start-end ,data node index

1-32=0

33-64=1

65-96=2

97-128=3

129-160=4

161-192=5

193-224=6

225-256=7

0-0=7

配置说明:

上面columns 标识将要分片的表字段,algorithm 分片函数,patternValue 即求模基数,defaoultNode默认节点,默认节点,小于0表示不设置默认节点,大于等于0表示设置默认节点,如果超出配置的范围,则使用默认节点,mapFile 配置文件路径。

配置文件中,1-32 即代表id%256 后分布的范围,如果在1-32 则在分区1,其他类推,如果id 非数据,则会分配在defaoultNode 默认节点。

截取数字做hash 求模范围约束

此种规则类似于取模范围约束,此规则支持数据符号字母取模。

<function name="sharding-by-pattern"

class="io.mycat.route.function.PartitionByPrefixPattern">

<property name="patternValue">256</property>

<property name="prefixLength">5</property>

<property name="mapFile">partition-pattern.txt</property>

</function>

partition-pattern.txt

1-4=0

5-8=1

9-12=2

13-16=3

17-20=4

21-24=5

25-28=6

29-32=7

0-0=7

配置说明:

patternValue 即求模基数,prefixLength截取的位数

mapFile 配置文件路径

配置文件中,1-32 即代表id%256 后分布的范围,如果在1-32 则在分区1,其他类推

此种方式类似方式6 只不过采取的是将列种获取前prefixLength 位列所有ASCII 码的和进行求模。

截取数字hash 解析

此规则是截取字符串中的int 数值hash 分片。

<function name="sharding-by-stringhash"class="io.mycat.route.function.PartitionByString">

<property name="partitionLength">512</property><!-- zero-based -->

<property name="partitionCount">2</property>

<property name="hashSlice">0:2</property>

</function>

配置说明:

函数中partitionLength 代表字符串hash 求模基数,

partitionCount 分区数,

hashSlice hash 预算位,即根据子字符串中int 值hash 运算

一致性hash

一致性hash 预算有效解决了分布式数据的扩容问题。

<function name="murmur" class="io.mycat.route.function.PartitionByMurmurHash">

<property name="seed">0</property><!-- 默认是0-->

<property name="count">2</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片-->

<property name="virtualBucketTimes">160</property><!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160 倍,也就是虚拟节点数是物理节点数的160 倍-->

<!--

<property name="weightMapFile">weightMapFile</property>

节点的权重,没有指定权重的节点默认是1。以properties 文件的格式填写,以从0 开始到count-1 的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1 代替-->

<!--

<property name="bucketMapPath">/etc/mycat/bucketMapPath</property>

用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的murmur hash 值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西-->

</function>

一致性哈希和虚拟一致性哈希

一致性哈希:

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

2.     然后采用同样的方法求出存储数据的键的哈希值,并映射到相同的圆上。

3.     然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过2的32次方仍然找不到服务器,就会保存到第一台服务器上。

一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

一致性哈希算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题,此时必然造成大量数据集中到Node A上,而只有极少量会定位到Node B上。

为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。具体做法可以在服务器ip或主机名的后面增加编号来实现。

例如,可以为每台服务器计算三个虚拟节点,于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六个虚拟节点:同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。

这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。

https://images2015.cnblogs.com/blog/498077/201608/498077-20160822172408386-366341651.png

按单月小时拆分

此规则是单月内按照小时拆分,最小粒度是小时,可以一天最多24 个分片,最少1 个分片,一个月完后下月从头开始循环。

每个月月尾,需要手工清理数据。

<function name="sharding-by-hour" class="io.mycat.route.function.LatestMonthPartion">

<property name="splitOneDay">24</property>

</function>

配置说明:

columns: 拆分字段,字符串类型(yyyymmddHH)

splitOneDay : 一天切分的分片数

范围求模分片

先进行范围分片计算出归属分片组,组内再根据组内分片数量求模。

<function name="rang-mod"

class="io.mycat.route.function.PartitionByRangeMod">

<property name="mapFile">partition-range-mod.txt</property>

<property name="defaultNode">21</property>

</function>

配置说明:

rang-mod 函数中mapFile 代表配置文件路径

defaultNode 超过范围后的默认节点顺序号,节点从0 开始。

partition-range-mod.txt

range start-end ,data node group size

以下配置一个范围代表一个分片组,=号后面的数字代表该分片组所拥有的分片的数量。

0-200M=5 //代表有5 个分片节点

200M1-400M=1

400M1-600M=4

600M1-800M=4

800M1-1000M=6

日期范围hash 分片

思想与范围求模一致,当由于日期在取模会有数据集中问题,所以改成hash 方法。

先根据日期分组,再根据时间hash 使得短期内数据分布的更均匀。

<function name="range-date-hash"

class="io.mycat.route.function.PartitionByRangeDateHash">

<property name="sBeginDate">2014-01-01 00:00:00</property>

<property name="sPartionDay">3</property>

<property name="dateFormat">yyyy-MM-dd HH:mm:ss</property>

<property name="groupPartionSize">6</property>

</function>

sPartionDay 代表多少天分一个分片

groupPartionSize 代表分片组的大小,在上述的例子中分片组共包含天数为6*3=18天

自然月分片

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

<function name="sharding-by-month" class="io.mycat.route.function.PartitionByMonth">

<property name="dateFormat">yyyy-MM-dd</property>

<property name="sBeginDate">2014-01-01</property>

</function>

配置说明:

dateFormat : 日期字符串格式,默认为yyyy-MM-dd

sBeginDate : 开始日期,无默认值

sEndDate:结束日期,无默认值

节点从0 开始分片

应用指定

此规则是在运行阶段有应用自主决定路由到那个分片。

<function name="sharding-by-substring"

class="io.mycat.route.function.PartitionDirectBySubString">

<property name="startIndex">0</property><!-- zero-based -->

<property name="size">2</property>

<property name="partitionCount">8</property>

<property name="defaultPartition">0</property>

</function>

配置说明:

此方法为直接根据字符子串(必须是数字)计算分区号(由应用传递参数,显式指定分区号)。

例如id=05-100000002在此配置中代表根据id 中从startIndex=0,开始,截取siz=2 位数字即05,05 就是获取的分区,如果没传

默认分配到defaultPartition

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值