时间:2021-07-01 10:21:17 帮助过:7人阅读
9.rule.xml详细描述表的分片规则,格式如下:
1 <tableRule name="分片规则名"> 2 <rule> 3 <columns>分片的列</columns> 4 <algorithm>分片算法名</algorithm> 5 </rule> 6 </tableRule> 7 <function name="分片算法名" class="算法实现类"> 8 <property name="算法参数">参数值</property> 9 </function>
原版样例:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mycat:rule SYSTEM "rule.dtd">
3 <mycat:rule xmlns:mycat="http://io.mycat/">
4 <tableRule name="rule1">
5 <rule>
6 <columns>id</columns>
7 <algorithm>func1</algorithm>
8 </rule>
9 </tableRule>
10 <tableRule name="rule2">
11 <rule>
12 <columns>user_id</columns>
13 <algorithm>func1</algorithm>
14 </rule>
15 </tableRule>
16 <tableRule name="sharding-by-intfile">
17 <rule>
18 <columns>sharding_id</columns>
19 <algorithm>hash-int</algorithm>
20 </rule>
21 </tableRule>
22 <tableRule name="auto-sharding-long">
23 <rule>
24 <columns>id</columns>
25 <algorithm>rang-long</algorithm>
26 </rule>
27 </tableRule>
28 <tableRule name="mod-long">
29 <rule>
30 <columns>id</columns>
31 <algorithm>mod-long</algorithm>
32 </rule>
33 </tableRule>
34 <tableRule name="sharding-by-murmur">
35 <rule>
36 <columns>id</columns>
37 <algorithm>murmur</algorithm>
38 </rule>
39 </tableRule>
40 <tableRule name="crc32slot">
41 <rule>
42 <columns>id</columns>
43 <algorithm>crc32slot</algorithm>
44 </rule>
45 </tableRule>
46 <tableRule name="sharding-by-month">
47 <rule>
48 <columns>create_time</columns>
49 <algorithm>partbymonth</algorithm>
50 </rule>
51 </tableRule>
52 <tableRule name="latest-month-calldate">
53 <rule>
54 <columns>calldate</columns>
55 <algorithm>latestMonth</algorithm>
56 </rule>
57 </tableRule>
58 <tableRule name="auto-sharding-rang-mod">
59 <rule>
60 <columns>id</columns>
61 <algorithm>rang-mod</algorithm>
62 </rule>
63 </tableRule>
64 <tableRule name="jch">
65 <rule>
66 <columns>id</columns>
67 <algorithm>jump-consistent-hash</algorithm>
68 </rule>
69 </tableRule>
70 <function name="murmur"
71 class="io.mycat.route.function.PartitionByMurmurHash">
72 <property name="seed">0</property><!-- 默认是0 -->
73 <property name="count">2</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
74 <property name="virtualBucketTimes">160</property><!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍 -->
75 <!-- <property name="weightMapFile">weightMapFile</property> 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 -->
76 <!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property>
77 用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西 -->
78 </function>
79 <function name="crc32slot"
80 class="io.mycat.route.function.PartitionByCRC32PreSlot">
81 </function>
82 <function name="hash-int"
83 class="io.mycat.route.function.PartitionByFileMap">
84 <property name="mapFile">partition-hash-int.txt</property>
85 </function>
86 <function name="rang-long"
87 class="io.mycat.route.function.AutoPartitionByLong">
88 <property name="mapFile">autopartition-long.txt</property>
89 </function>
90 <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
91 <!-- how many data nodes -->
92 <property name="count">3</property>
93 </function>
94 ?
95 <function name="func1" class="io.mycat.route.function.PartitionByLong">
96 <property name="partitionCount">8</property>
97 <property name="partitionLength">128</property>
98 </function>
99 <function name="latestMonth"
100 class="io.mycat.route.function.LatestMonthPartion">
101 <property name="splitOneDay">24</property>
102 </function>
103 <function name="partbymonth"
104 class="io.mycat.route.function.PartitionByMonth">
105 <property name="dateFormat">yyyy-MM-dd</property>
106 <property name="sBeginDate">2015-01-01</property>
107 </function>
108 <function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod">
109 <property name="mapFile">partition-range-mod.txt</property>
110 </function>
111 <function name="jump-consistent-hash" class="io.mycat.route.function.PartitionByJumpConsistentHash">
112 <property name="totalBuckets">3</property>
113 </function>
114 </mycat:rule>
部分常用的分片规则算法说明:
PartitionByMurmurHash(一致性hash):将物理节点虚拟并映射为一个“一致性hash环”;
PartitionByCRC32PreSlot(crc32slot 算法):crc32(key)%102400=slot,slot 按照范围均匀分布在 dataNode 上;
LatestMonthPartion(单月小时拆分):单月内按照小时拆分,最小粒度是小时,可以一天最多 24 个分片,最少 1 个分片,一个月完后下月 从头开始循环;
PartitionByMonth(自然月):按自然月分片;
PartitionByRangeMod(范围求模):先进行范围分片计算出分片组,组内再求模;
PartitionByJumpConsistentHash(一致性hash):另一种一致性hash算法;
PartitionByFileMap(枚举):通过在配置文件中配置可能的枚举 id,自己配置分片,本规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国省份区县是固定的;
PartitionByLong(固定分片 hash 算法):取 id 的二进制低 10 位取模运算,即( id 二进制) &1111111111,partitionCount分片个数,partitionLength分片长度,默认这两个参数的向量积为1024;
AutoPartitionByLong(范围约定):按照提前规划好分片字段范围计算属于哪个分片,start <= range <= end;
PartitionByMod(求模):即根据 id 进行十进制求模预算,相比固定分片 hash,此种在批量插入时可能存在批量插入单事务插入多数据分片,增大事务一致性难度;
PartitionByDate(按天分片):即根据指定的格式,起止日期,按日期划分,如果配置了 sEndDate 则代表数据达到了这个日期的分片后后循环从开始分片插入;
10.情况一:如果DB是一主一从
:需注意这里的主从复制由Mysql实现,Mycat不负责数据复制功能
。只需配置server.xml和schema.xml即可: 本次server.xml实例:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mycat:server SYSTEM "server.dtd"> 3 <mycat:server xmlns:mycat="http://io.mycat/"> 4 <system> 5 <property name="nonePasswordLogin">0</property> 6 <property name="useHandshakeV10">1</property> 7 <property name="useSqlStat">0</property> 8 <property name="useGlobleTableCheck">0</property> 9 <property name="sqlExecuteTimeout">300</property> 10 <property name="sequnceHandlerType">2</property> 11 <property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property> 12 <property name="subqueryRelationshipCheck">false</property> 13 <property name="processorBufferPoolType">0</property> 14 <property name="handleDistributedTransactions">0</property> 15 <property name="useOffHeapForMerge">0</property> 16 <property name="memoryPageSize">64k</property> 17 <property name="spillsFileBufferSize">1k</property> 18 <property name="useStreamOutput">0</property> 19 <property name="systemReserveMemorySize">384m</property> 20 <property name="useZKSwitch">false</property> 21 <property name="strictTxIsolation">false</property> 22 <property name="useZKSwitch">true</property> 23 </system> 24 <user name="mycat" defaultAccount="true"> 25 <property name="password">12345678</property> 26 <property name="schemas">dubbo_db</property> 27 </user> 28 </mycat:server>
schema.xml示例:
1 <?xml version="1.0"?> 2 <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> 3 <!-- 数据库配置,与server.xml中的数据库对应 --> 4 <mycat:schema xmlns:mycat="http://io.mycat/"> 5 <schema name="dubbo_db" checkSQLschema="true" sqlMaxLimit="100"> 6 <table name="dubbo_delivery" primaryKey="ID" dataNode="dn1"/> 7 <table name="dubbo_finance" primaryKey="ID" dataNode="dn1 "/> 8 <table name="dubbo_item" primaryKey="ID" dataNode="dn1 " /> 9 <table name="dubbo_order" primaryKey="ID" dataNode="dn1"/> 10 <table name="dubbo_order_detail" primaryKey="ID" dataNode="dn1 "/> 11 <table name="dubbo_stock" primaryKey="ID" dataNode="dn1 " /> 12 </schema> 13 <!-- 分片配置 --> 14 <dataNode name="dn1" dataHost="localhost1" database="dubbo_db" /> 15 <!-- 物理数据库配置 --> 16 <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" 17 writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> 18 <heartbeat>select user()</heartbeat> 19 <writeHost host="hostM1" url="192.168.1.204:3306" user="root" password="abcd@1234"> 20 <readHost host="hostS2" url="192.168.1.205:3306" user="root" password="abcd@1234" /> 21 </writeHost> 22 </dataHost> 23 </mycat:schema>
11.情况二,即本期目标架构,DB是两主一从:server.xml不变, 本次schema.xml实例:
1 <?xml version="1.0"?> 2 <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> 3 <!-- 数据库配置,与server.xml中的数据库对应 --> 4 <mycat:schema xmlns:mycat="http://io.mycat/"> 5 <schema name="dubbo_db" checkSQLschema="true" sqlMaxLimit="100"> 6 <table name="dubbo_delivery" primaryKey="ID" dataNode="dn1"/> 7 <table name="dubbo_finance" primaryKey="ID" dataNode="dn1,dn2" rule="rule1"/> 8 <table name="dubbo_item" primaryKey="ID" dataNode="dn1,dn2" rule="rule2"/> 9 <table name="dubbo_order" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-murmur"/> 10 <table name="dubbo_order_detail" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-month"/> 11 <table name="dubbo_stock" primaryKey="ID" dataNode="dn1" /> 12 </schema> 13 <!-- 分片配置 --> 14 <dataNode name="dn1" dataHost="localhost1" database="dubbo_db" /> 15 <dataNode name="dn2" dataHost="localhost2" database="dubbo_db" /> 16 <!-- 物理数据库配置 --> 17 <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" 18 writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> 19 <heartbeat>select user()</heartbeat> 20 <writeHost host="hostM1" url="192.168.1.204:3306" user="root" password="abcd@1234"> 21 <readHost host="hostS2" url="192.168.1.205:3306" user="root" password="abcd@1234" /> 22 </writeHost> 23 </dataHost> 24 <dataHost name="localhost2" maxCon="1000" minCon="10" balance="0" 25 writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> 26 <heartbeat>select user()</heartbeat> 27 <writeHost host="hostM2" url="192.168.1.206:3306" user="root" password="abcd@1234" /> 28 </dataHost> 29 </mycat:schema>
本次rule.xml实例:只有使用了分片模式时,才需要配置rule规则,这里写了三种rule,其实也没全部用上:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mycat:rule SYSTEM "rule.dtd"> 3 <mycat:rule xmlns:mycat="http://io.mycat/"> 4 <!--规则定义--> 5 <tableRule name="sharding-by-murmur"> 6 <rule> 7 <columns>id</columns> 8 <algorithm>murmur</algorithm> 9 </rule> 10 </tableRule> 11 <!--自定义规则--> 12 <tableRule name="rule1"> 13 <rule> 14 <columns>userr_id</columns> 15 <algorithm>func1</algorithm> 16 </rule> 17 </tableRule> 18 <tableRule name="rule2"> 19 <rule> 20 <columns>id</columns> 21 <algorithm>func2</algorithm> 22 </rule> 23 </tableRule> 24 <tableRule name="sharding-by-month"> 25 <rule> 26 <columns>create_time</columns> 27 <algorithm>partbymonth</algorithm> 28 </rule> 29 </tableRule> 30 <!--规则算法实现--> 31 <function name="murmur" 32 class="io.mycat.route.function.PartitionByMurmurHash"> 33 <property name="seed">0</property><!-- 默认是0 --> 34 <property name="count">2</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片 --> 35 <property name="virtualBucketTimes">160</property><!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍 --> 36 <!-- <property name="weightMapFile">weightMapFile</property> 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替 --> 37 <!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property> 38 用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,就不会输出任何东西 --> 39 </function> 40 <function name="func1" class="io.mycat.route.function.PartitionByLong"> 41 <!--分片数量,partitionCount*partitionLength=1024--> 42 <property name="partitionCount">2</property> 43 <property name="partitionLength">512</property> 44 </function> 45 <function name="func2" class="io.mycat.route.function.PartitionByLong"> 46 <property name="partitionCount">8</property> 47 <property name="partitionLength">128</property> 48 </function> 49 <function name="partbymonth" 50 class="io.mycat.route.function.PartitionByMonth"> 51 <property name="dateFormat">yyyy-MM-dd</property> 52 <property name="sBeginDate">2015-01-01</property> 53 </function> 54 </mycat:rule>
12.测试:配置好mycat/conf/下的3个xml文件,即配置好了Mycat与物理DB的连接,应用端连接仅需修改连接串端口为Mycat的IP+端口,账号为server.xml中user信息,注意:
要写上默认schema,否则启动应用报Mycat no chose
错,
13.此处有坑!如果Mysql是独立安装在linux上,需要对远程访问打开,否则访问默认仅限本地,导致远程连接一直报错,以开放root
用户远程连接为例:
mysql> use mysql;
mysql> update user set Host=‘%‘ where User=‘root‘;
mysql> quit;
再重启mysql:
[root@localhost ~]# systemctl restart mysqld
启动Mycat:
[root@localhost ~]# cd /usr/mycat/mycat/bin
[root@localhost bin]# ./mycat start
mycat启动成功:
如果启动有问题,使用以下命令查看log:
[root@localhost conf]# tail -F /usr/mycat/mycat/logs/wrapper.log
[root@localhost conf]# tail -F /usr/mycat/mycat/logs/mycat.log
然后可以在window上使用如MysqlWorkbench,Navicat测试下是否连接正常,并测试下Mycat连接:
为了集中测试代码,我只改写了finance模块,写个service方法:com.biao.mall.service.DubboFinanceServiceImpl中:
1 //插入1000条数据,看data分布
2 @Override
3 public void testMycat(){
4 DubboFinanceEntity financeEntity = new DubboFinanceEntity();
5 for (int i = 0; i < 1000; i++) {
6 financeEntity.setUserId(String.valueOf(i+100));
7 financeDao.insert(financeEntity);
8 }
9 return "testMycat successfully";
10 }
写个controller方法跑一跑:
@RestController
@RequestMapping("/finance")
public class DubboFinanceController {
private DubboFinanceServiceImpl financeService;
@Autowired
public DubboFinanceController(DubboFinanceServiceImpl financeService) {
this.financeService = financeService;
}
@RequestMapping("/mycat")
public void testMycat(){
return financeService.testMycat();
}
}
启动:ZK---> business --> finance, URI来一个!
DB情况,请看数量和ID分布,红色数字是IP:
这里只测试了两主一从和一种分片规则,其他请君自测!
13.代码地址:其中的day16,https://github.com/xiexiaobiao/dubbo-project.git
后记:
1.认识Mycat的关键特性:
2.认清Mycat的局限性:
目前只支持跨库join2个表,不支持3 表及其以上跨库 join ;
Mycat并没有根据二阶段提交协议实现 XA事务,而是只保证 prepare 阶段数据一致性的弱XA事务,分布式事务场景下,强一致性无法保证;
分页排序场景下,会一次查询所有分片,再集中排序分页,有性能瓶颈;
不同类型DB适配一般,如Oracle/SQLServer等,由于SQL语法差异,须做彻底的语句兼容测试;
没有API配置方法,只有XML方式配置,十分过时;
3.Mycat作为DB上一层的重量级中间件,统一了入口,实际上也破坏了分布式的定义,未能充分发挥DB层的效能,所以也有很多不看好的声音,DB独立使用,更能发挥灵活自由配置,直接对接应用层更为高效。
4.总结:Mycat框架的使用,需持谨慎态度,至少目前来看如此。
推荐阅读:
Dubbo学习系列之十二(Quartz任务调度)
Linux下Mysql集群使用
Dubbo学习系列之十一(Dashboard+Nacos规则推送)
Dubbo学习系列之十(Sentinel之限流与降级)
Dubbo学习系列之九(Shiro+JWT权限管理)
Dubbo学习系列之十三(Mycat数据库代理)
标签:emctl ddl jdb XML hash算法 模拟 work dash connect