mycat分片

文章目录

1. 分片枚举

总配置文件 如下,下面就编写修改的部分

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
		<!--分库的实现-->
		<table name="customer" dataNode="dn2"></table>
		<!--分表的实现-->
		<table name="orders" dataNode="dn1,dn2" rule="mod_rule"></table>
		<!-- 枚举分片 -->
		<table name="orders_ware_info" dataNode="dn1,dn2" rule="sharding-by-intfile"></table>
	</schema>
	<!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
		/> -->
	<dataNode name="dn1" dataHost="localhost1" database="orders" />
	<dataNode name="dn2" dataHost="localhost2" database="orders"/>

	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<!-- can have multi write hosts -->
		<writeHost host="hostM1" url="192.168.37.129:3306" user="root"
				   password="root">
				<!-- <readHost host="hostS1" url="192.168.37.130:3306" user="root" password="root"></readHost>	 -->
		</writeHost>
	
		<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
	</dataHost>
	<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM2" url="192.168.37.131:3306" user="root"
				   password="root">
				<!-- <readHost host="hostS2" url="192.168.37.132:3306" user="root" password="root"></readHost>	 -->
		</writeHost>
	</dataHost>		
	<!--
		<dataHost name="sequoiadb1" maxCon="1000" minCon="1" balance="0" dbType="sequoiadb" dbDriver="jdbc">
		<heartbeat> 		</heartbeat>
		 <writeHost host="hostM1" url="sequoiadb://1426587161.dbaas.sequoialab.net:11920/SAMPLE" user="jifeng" 	password="jifeng"></writeHost>
		 </dataHost>

	  <dataHost name="oracle1" maxCon="1000" minCon="1" balance="0" writeType="0" 	dbType="oracle" dbDriver="jdbc"> <heartbeat>select 1 from dual</heartbeat>
		<connectionInitSql>alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'</connectionInitSql>
		<writeHost host="hostM1" url="jdbc:oracle:thin:@127.0.0.1:1521:nange" user="base" 	password="123456" > </writeHost> </dataHost>

		<dataHost name="jdbchost" maxCon="1000" 	minCon="1" balance="0" writeType="0" dbType="mongodb" dbDriver="jdbc">
		<heartbeat>select 	user()</heartbeat>
		<writeHost host="hostM" url="mongodb://192.168.0.99/test" user="admin" password="123456" ></writeHost> </dataHost>

		<dataHost name="sparksql" maxCon="1000" minCon="1" balance="0" dbType="spark" dbDriver="jdbc">
		<heartbeat> </heartbeat>
		 <writeHost host="hostM1" url="jdbc:hive2://feng01:10000" user="jifeng" 	password="jifeng"></writeHost> </dataHost> -->

	<!-- <dataHost name="jdbchost" maxCon="1000" minCon="10" balance="0" dbType="mysql"
		dbDriver="jdbc"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1"
		url="jdbc:mysql://localhost:3306" user="root" password="123456"> </writeHost>
		</dataHost> -->
</mycat:schema>

1.1 修改schema.xml文件

		<!-- 枚举分片 -->
<table name="orders_ware_info" dataNode="dn1,dn2" rule="sharding-by-intfile"></table>

1.2 修改rule.xml文件

<!-- 枚举分片 -->
	<tableRule name="sharding-by-intfile">
		<rule>
			<columns>areacode</columns>
			<algorithm>hash-int</algorithm>
		</rule>
	</tableRule>
			<!--
	columns:分片字段, algorithm:分片函数
	mapFile: 标识配置文件名称, type: 0为int型、 非0为String,
	defaultNode: 默认节点:小于 0 表示不设置默认节点,大于等于 0 表示设置默认节点,
	设置默认节点如果碰到不识别的枚举值,就让它路由到默认节点,如不设置不识别就报错
	-->
	<function name="hash-int"
			  class="io.mycat.route.function.PartitionByFileMap">
		<property name="mapFile">partition-hash-int.txt</property>
		<property name="type">1</property>
		<!-- 默认的枚举值 -->
		<property name="defaultNode">0</property>
	</function>

1.3 修改partition-hash-int.txt文件

110=0
120=1

1.4 重启mycat 服务

1.5 mycat中创建表

CREATE TABLE orders_ware_info
(
`id` INT AUTO_INCREMENT comment '编号',
`order_id` INT comment '订单编号',
`address` VARCHAR(200) comment '地址',
`areacode` VARCHAR(20) comment '区域编号',
PRIMARY KEY(id)
);

INSERT INTO orders_ware_info(id, order_id,address,areacode) VALUES (1,1,'北京','110');
INSERT INTO orders_ware_info(id, order_id,address,areacode) VALUES (2,2,'天津','120');

1.6效果

在这里插入图片描述
在这里插入图片描述


2. 范围分片

2.1修改schema.xml文件

	<!-- 范围分片 -->
   	<table name="payment_info" dataNode="dn1,dn2" rule="auto-sharding-long"></table>

2.2 修改rule.xml文件

<tableRule name="auto-sharding-long">
   	<rule>
   		<columns>order_id</columns>
   		<algorithm>rang-long</algorithm>
   	</rule>
   </tableRule>
   	<function name="rang-long"
   		  class="io.mycat.route.function.AutoPartitionByLong">
   	<property name="mapFile">autopartition-long.txt</property>
   	<property name="defaultNode">0</property>
   </function>

2.3 修改autopartition-long.txt文件

0-100=0
100-200=1

2.4 重启mycat服务

2.5 mycat中创建表

CREATE TABLE payment_info
(
`id` INT AUTO_INCREMENT comment '编号',
`order_id` INT comment '订单编号',
`payment_status` INT comment '支付状态',
PRIMARY KEY(id)
);

INSERT INTO payment_info (id,order_id,payment_status) VALUES (1,99,0);
INSERT INTO payment_info (id,order_id,payment_status) VALUES (2,98,1);
INSERT INTO payment_info (id,order_id ,payment_status) VALUES (3,103,0);
INSERT INTO payment_info (id,order_id,payment_status) VALUES (4,104,1);

2.6 效果

在这里插入图片描述
在这里插入图片描述


3. 范围取模算法

该算法为先进行范围分片,计算出分片组,组内再求模,综合了范围分片和求模分片的优点。分片组内使用求模可以保证组内的数据分步比较均匀,分片组之间采用范围分片可以兼顾范围分片的特点。事先规定好分片的数量,数据扩容时按分片组扩容,则原有分片组的数据不需要迁移。由于分片组内的数据分步比较均匀,所以分片组内可以避免热点数据问题。

3.1 修改schema.xml文件

<!-- 范围取模算法 -->
		<table name="person" dataNode="dn1,dn2,dn3" rule="auto-sharding-rang-mod"></table>
	<dataNode name="dn3" dataHost="localhost3" database="orders"/>
		<dataHost name="localhost3" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM3" url="192.168.37.130:3306" user="root"
				   password="root">
				<!-- <readHost host="hostS2" url="192.168.37.132:3306" user="root" password="root"></readHost>	 -->
		</writeHost>
	</dataHost>				

3.2 修改rule.xml

	<tableRule name="auto-sharding-rang-mod">
		<rule>
			<columns>id</columns>
			<algorithm>rang-mod</algorithm>
		</rule>
	</tableRule>
	<function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod">
		<property name="mapFile">partition-range-mod.txt</property>
	</function>

3.3 修改partition-range-mod.txt文件

# range start-end ,data node group size
#表示0到一万的范围中,两台机器取模
0-1M=2
#表示10000到20000 
1M1-2M=1

3.4 重启mycat服务

3.5 mycat创建表,并插入数据

CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into person(id,name) values(9999,'zhangsan1');
insert into person(id,name) values(10000,'zhangsan2');
insert into person(id,name) values(10001,'zhangsan3');
insert into person(id,name) values(20000,'zhangsan4');

3.6 效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


4. 固定分片hash算法

4.1 修改schema.xml文件

		<!-- 固定分片hash算法 -->
		<table name="user" primaryKey="id" dataNode="dn1,dn2,dn3" rule="rule1"></table>

4.2 修改rule.xml文件

<!--
columns标识将要分片的表字段
algorithm为分片函数
partitionCount为分片个数列表
partitionLength为分片范围列表,分区长度默认最大为1024,即最大支持1024个分区
约束如下:
	count,length 两个数组的长度必须是一致的。
1024 = sum((count[i]*length[i])). count 和 length 两个向量的点积恒等于 1024
-->
	<tableRule name="rule1">
		<rule>
			<columns>id</columns>
			<algorithm>func1</algorithm>
		</rule>
	</tableRule>
	<function name="func1" class="io.mycat.route.function.PartitionByLong">
		<property name="partitionCount">2,1</property>
		<property name="partitionLength">256,512</property>
	</function>

4.3 重启mycat服务

4.4 在mycat中创建表并插入数据

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into user(id,name) values(1023,'zhangsan1');
insert into user(id,name) values(1024,'zhangsan2');
insert into user(id,name) values(266,'zhangsan3');
insert into user(id,name) values(255,'zhangsan4');

4.5 效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


5. 取模范围算法

5.1 修改schema.xml文件

<table name="user2" primaryKey="id" dataNode="dn1,dn2,dn3" rule="sharding-by-pattern"
></table>

5.2 修改rule.xml

<!--
columns标识将要分片的表字段
algorithm为分片函数
mapFile:切分规则配置文件
patternValue:求模基数
defaultNode:默认节点,小于0表示不设置默认节点,大于等于0表示设置默认节点,如果超出配置的范围,则使用默认节点;
-->
<tableRule name="sharding-by-pattern">
		<rule>
			<columns>id</columns>
			<algorithm>sharding-by-pattern</algorithm>
		</rule>
	</tableRule>

	<function name="sharding-by-pattern" class="io.mycat.route.function.PartitionByPattern">
		<property name="mapFile">partition-pattern.txt</property>
		<property name="patternVAlue">256</property>
        <property name="defaultNode">0</property>
	</function>

5.3 修改partition-pattern.txt文件

0-86=0
87-173=1
174-256=2

5.4 重启mycat

5.5 效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


6. 按照日期范围分片

6.1 修改schema.xml文件

	<!-- 按日期范围分类 -->
		<table name="login_info"  dataNode="dn1,dn2" rule="sharding_by_date"></table>

6.2 修改rule.xml文件

注意:sPartionDay的数量乘以机器的数量要等于时间的范围,不然会报错

	<tableRule name="sharding_by_date">
		<rule>
			<columns>login_date</columns>
			<algorithm>shardingByDate</algorithm>
		</rule>
	</tableRule>
	<!--
	columns:分片字段, algorithm:分片函数
	dateFormat :日期格式
	sBeginDate :开始日期
	sEndDate:结束日期,则代表数据达到了这个日期的分片后循环从开始分片插入
	sPartionDay :分区天数,即默认从开始日期算起,分隔 2 天一个分区
	**sPartionDay+sBeginDate<sEndDate<sPartionDay*dataNode数**
	-->
	<function name="shardingByDate" class="io.mycat.route.function.PartitionByDate">
		<property name="dateFormat">yyyy-MM-dd</property>
		<property name="sBeginDate">2020-06-01</property>
		<property name="sEndDate">2020-06-04</property>
		<property name="sPartionDay">2</property>
	</function>

6.3 重启mycat服务

6.4 通过mycat创建表并插入测试数据

CREATE TABLE login_info
(
`id` INT AUTO_INCREMENT comment '编号',
`user_id` INT comment '用户编号',
`login_date` date comment '登录日期',
PRIMARY KEY(id)
);

INSERT INTO login_info(id,user_id,login_date) VALUES (1,101,'2020-06-01');
INSERT INTO login_info(id,user_id,login_date) VALUES (2,102,'2020-06-02');
INSERT INTO login_info(id,user_id,login_date) VALUES (3,103,'2020-06-03');
INSERT INTO login_info(id,user_id,login_date) VALUES (4,104,'2020-06-04');
INSERT INTO login_info(id,user_id,login_date) VALUES (5,103,'2020-06-05');
INSERT INTO login_info(id,user_id,login_date) VALUES (6,104,'2020-06-06');

6.5 测试结果

形成一个闭环的轮询插入

在这里插入图片描述
在这里插入图片描述

7. 按单月小时分片

​ 此规则是单月内按照小时拆分,最小粒度是小时,可以一天最多24个分片,最少一个分片,一个月完成后下个月开始循环,每个月月尾,需要手工清理数据。

7.1、修改schema.xml文件

<table name="user6" dataNode="dn1,dn2,dn3" rule="sharding-by-hour"></table>

7.2、修改rule.xml文件

<tableRule name="sharding-by-hour">
<rule>
<columns>create_time</columns>
<algorithm>sharding-by-hour</algorithm>
</rule>
</tableRule>
<!--
columns: 拆分字段,字符串类型(yyyymmddHH)
splitOneDay : 一天切分的分片数
-->
<function name="sharding-by-hour" class="io.mycat.route.function.LatestMonthPartion">
<property name="splitOneDay">3</property>
</function>

##​ 7.3、重启mycat服务

7.4创建mycat表

create table user6(
id int not null,
name varchar(64),
create_time varchar(10)
);

insert into user6(id,name,create_time) values(1,'steven','2020060100');
insert into user6(id,name,create_time) values(1,'steven','2020060101');
insert into user6(id,name,create_time) values(1,'steven','2020060102');
insert into user6(id,name,create_time) values(1,'steven','2020060103');
insert into user6(id,name,create_time) values(1,'steven','2020060104');
insert into user6(id,name,create_time) values(1,'steven','2020060105');
insert into user6(id,name,create_time) values(1,'steven','2020060106');
insert into user6(id,name,create_time) values(1,'steven','2020060107');
insert into user6(id,name,create_time) values(1,'steven','2020060108');
insert into user6(id,name,create_time) values(1,'steven','2020060109');
insert into user6(id,name,create_time) values(1,'steven','2020060110');
insert into user6(id,name,create_time) values(1,'steven','2020060111');
insert into user6(id,name,create_time) values(1,'steven','2020060112');
insert into user6(id,name,create_time) values(1,'steven','2020060113');
insert into user6(id,name,create_time) values(1,'steven','2020060114');
insert into user6(id,name,create_time) values(1,'steven','2020060115');
insert into user6(id,name,create_time) values(1,'steven','2020060116');
insert into user6(id,name,create_time) values(1,'steven','2020060117');
insert into user6(id,name,create_time) values(1,'steven','2020060118');
insert into user6(id,name,create_time) values(1,'steven','2020060119');
insert into user6(id,name,create_time) values(1,'steven','2020060120');
insert into user6(id,name,create_time) values(1,'steven','2020060121');
insert into user6(id,name,create_time) values(1,'steven','2020060122');
insert into user6(id,name,create_time) values(1,'steven','2020060123');
insert into user6(id,name,create_time) values(1,'steven','2020060200');
insert into user6(id,name,create_time) values(1,'steven','2020060201');
insert into user6(id,name,create_time) values(1,'steven','2020060202');
insert into user6(id,name,create_time) values(1,'steven','2020060203');
insert into user6(id,name,create_time) values(1,'steven','2020060204');
insert into user6(id,name,create_time) values(1,'steven','2020060205');
insert into user6(id,name,create_time) values(1,'steven','2020060206');
insert into user6(id,name,create_time) values(1,'steven','2020060207');
insert into user6(id,name,create_time) values(1,'steven','2020060208');
insert into user6(id,name,create_time) values(1,'steven','2020060209');
insert into user6(id,name,create_time) values(1,'steven','2020060210');
insert into user6(id,name,create_time) values(1,'steven','2020060211');

​ 当运行完成之后会发现,第一天的数据能够正常的插入成功,均匀的分散到3个分片上,但是第二天的数据就无法成功分散了,原因就在于我们的数据分片不够,所以这种方式几乎没有人使用。

8. 日期范围hash分片

思想与范围求模一致,当由于日期在取模会有数据集中问题,所以改成了hash方法。先根据时间hash使得短期内数据分布的更均匀,有点可以避免扩容时的数据迁移,又可以一定程度上避免范围分片的热点问题,要求日期格式尽量精确,不然达不到局部均匀的目的。

8.1 修改schema.xml文件

<table name="user7" dataNode="dn1,dn2,dn3" rule="rangeDateHash"></table>

8.2 修改rule.xml文件

	<tableRule name="rangeDateHash">
		<rule>
			<columns>create_time</columns>
			<algorithm>range-date-hash</algorithm>
		</rule>
	</tableRule>
	<!--
columns: 拆分字段,字符串类型(yyyymmddHH)
algorithm:分片函数
sBeginDate:指定开始的日期,与dateFormat格式一致
sPartionDay:代表多少天一组
dateFormat:指定的日期格式,符合java标准
groupPartionSize:表示的是多少个节点为一组,1表示3个节点各为一组,2表示2个节点为一组,3表示三个节点为一组
-->
<function name="range-date-hash" class="io.mycat.route.function.PartitionByRangeDateHash">
	<property name="sBeginDate">2020-06-01 00:00:00</property>
	<property name="sPartionDay">3</property>
	<property name="dateFormat">yyyy-MM-dd HH:mm:ss</property>
	<property name="groupPartionSize">1</property>
</function>

9. 冷热数据分片

根据日期查询冷热数据分布,最近n个月的到实时交易库查询,其他的到其他库中

9.1 修改shcema.xml文件

<table name="user8" dataNode="dn1,dn2,dn3" rule="sharding-by-hotdate" />

9.2 修改rule.xml文件

tableRule name="sharding-by-hotdate">
		<rule>
			<columns>create_time</columns>
			<algorithm>sharding-by-hotdate</algorithm>
		</rule>
	</tableRule>
<!--
dataFormat:时间格式化
sLastDay:热数据的天数 表示当前时间往前推的天数,存在热数据节点
sPartionDay:冷数据的分片天数(按照天数分片),表示过了热数据节点的时间,往前推30天存冷数据,其他的数据插入会报错
-->
<function name="sharding-by-hotdate" class="io.mycat.route.function.PartitionByHotDate">
	<property name="dateFormat">yyyy-MM-dd</property>
	<property name="sLastDay">10</property>
	<property name="sPartionDay">30</property>
</function>

9.3 重启mycat

9.4 创建表和数据

CREATE TABLE  user8(create_time   timestamp NULL ON UPDATE CURRENT_TIMESTAMP  ,`db_nm`  varchar(20) NULL);
INSERT INTO user8 (create_time,db_nm) VALUES ('2020-06-01', database());
INSERT INTO user8 (create_time,db_nm) VALUES ('2020-06-10', database());
INSERT INTO user8 (create_time,db_nm) VALUES ('2020-06-11', database());
INSERT INTO user8 (create_time,db_nm) VALUES ('2020-06-21', database());
INSERT INTO user8 (create_time,db_nm) VALUES ('2020-06-30', database());
INSERT INTO user8 (create_time,db_nm) VALUES ('2020-07-30', database());

9.5 效果

当前实际2022-08-08

在这里插入图片描述
在这里插入图片描述

10. 自然月分片

10.1、修改schema.xml文件

<table name="user9" dataNode="dn1,dn2,dn3" rule="sharding-by-month" />

10. 2、修改rule.xml文件

<tableRule name="sharding-by-month">
<rule>
<columns>create_time</columns>
<algorithm>sharding-by-month</algorithm>
</rule>
</tableRule>
<!--
columns: 分片字段,字符串类型
dateFormat : 日期字符串格式
sBeginDate : 开始日期
表示的是每一月一个分片,当前只有3个分片,所以只能存3个月的数据
-->
<function name="sharding-by-month" class="io.mycat.route.function.PartitionByMonth">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2019-01-01</property>
</function>

10.3重启mycat服务

10.4创建mycat表

CREATE TABLE  user9(id int,name varchar(10),create_time varchar(20));
insert into user9(id,name,create_time) values(111,'zhangsan','2019-01-01');
insert into user9(id,name,create_time) values(111,'zhangsan','2019-03-01');
insert into user9(id,name,create_time) values(111,'zhangsan','2019-05-01');
insert into user9(id,name,create_time) values(111,'zhangsan','2019-07-01');
insert into user9(id,name,create_time) values(111,'zhangsan','2019-09-01');
insert into user9(id,name,create_time) values(111,'zhangsan','2019-11-01');

11. 一致性hash分片

11.1 一致性hash原理

​ 在了解一致性哈希算法之前,最好先了解一下缓存中的一个应用场景,了解了这个应用场景之后,再来理解一致性哈希算法,就容易多了,也更能体现出一致性哈希算法的优点,那么,我们先来描述一下这个经典的分布式缓存的应用场景。

1、场景描述

​ 假设,我们有三台缓存服务器,用于缓存图片,我们为这三台缓存服务器编号为0号、1号、2号,现在,有3万张图片需要缓存,我们希望这些图片被均匀的缓存到这3台服务器上,以便它们能够分摊缓存的压力。也就是说,我们希望每台服务器能够缓存1万张左右的图片,那么,我们应该怎样做呢?如果我们没有任何规律的将3万张图片平均的缓存在3台服务器上,可以满足我们的要求吗?可以!但是如果这样做,当我们需要访问某个缓存项时,则需要遍历3台缓存服务器,从3万个缓存项中找到我们需要访问的缓存,遍历的过程效率太低,时间太长,当我们找到需要访问的缓存项时,时长可能是不能被接收的,也就失去了缓存的意义,缓存的目的就是提高速度,改善用户体验,减轻后端服务器压力,如果每次访问一个缓存项都需要遍历所有缓存服务器的所有缓存项,想想就觉得很累,那么,我们该怎么办呢?原始的做法是对缓存项的键进行哈希,将hash后的结果对缓存服务器的数量进行取模操作,通过取模后的结果,决定缓存项将会缓存在哪一台服务器上,这样说可能不太容易理解,我们举例说明,仍然以刚才描述的场景为例,假设我们使用图片名称作为访问图片的key,假设图片名称是不重复的,那么,我们可以使用如下公式,计算出图片应该存放在哪台服务器上。

hash(图片名称)% N

​ 因为图片的名称是不重复的,所以,当我们对同一个图片名称做相同的哈希计算时,得出的结果应该是不变的,如果我们有3台服务器,使用哈希后的结果对3求余,那么余数一定是0、1或者2,没错,正好与我们之前的服务器编号相同,如果求余的结果为0, 我们就把当前图片名称对应的图片缓存在0号服务器上,如果余数为1,就把当前图片名对应的图片缓存在1号服务器上,如果余数为2,同理,那么,当我们访问任意一个图片的时候,只要再次对图片名称进行上述运算,即可得出对应的图片应该存放在哪一台缓存服务器上,我们只要在这一台服务器上查找图片即可,如果图片在对应的服务器上不存在,则证明对应的图片没有被缓存,也不用再去遍历其他缓存服务器了,通过这样的方法,即可将3万张图片随机的分布到3台缓存服务器上了,而且下次访问某张图片时,直接能够判断出该图片应该存在于哪台缓存服务器上,这样就能满足我们的需求了,我们暂时称上述算法为HASH算法或者取模算法,取模算法的过程可以用下图表示。

在这里插入图片描述

​ 但是,使用上述HASH算法进行缓存时,会出现一些缺陷,试想一下,如果3台缓存服务器已经不能满足我们的缓存需求,那么我们应该怎么做呢?没错,很简单,多增加两台缓存服务器不就行了,假设,我们增加了一台缓存服务器,那么缓存服务器的数量就由3台变成了4台,此时,如果仍然使用上述方法对同一张图片进行缓存,那么这张图片所在的服务器编号必定与原来3台服务器时所在的服务器编号不同,因为除数由3变为了4,被除数不变的情况下,余数肯定不同,这种情况带来的结果就是当服务器数量变动时,所有缓存的位置都要发生改变,换句话说,当服务器数量发生改变时,所有缓存在一定时间内是失效的,当应用无法从缓存中获取数据时,则会向后端服务器请求数据,同理,假设3台缓存中突然有一台缓存服务器出现了故障,无法进行缓存,那么我们则需要将故障机器移除,但是如果移除了一台缓存服务器,那么缓存服务器数量从3台变为2台,如果想要访问一张图片,这张图片的缓存位置必定会发生改变,以前缓存的图片也会失去缓存的作用与意义,由于大量缓存在同一时间失效,造成了缓存的雪崩,此时前端缓存已经无法起到承担部分压力的作用,后端服务器将会承受巨大的压力,整个系统很有可能被压垮,所以,我们应该想办法不让这种情况发生,但是由于上述HASH算法本身的缘故,使用取模法进行缓存时,这种情况是无法避免的,为了解决这些问题,一致性哈希算法诞生了。

​ 我们来回顾一下使用上述算法会出现的问题。

问题1:当缓存服务器数量发生变化时,会引起缓存的雪崩,可能会引起整体系统压力过大而崩溃(大量缓存同一时间失效)。

问题2:当缓存服务器数量发生变化时,几乎所有缓存的位置都会发生改变,怎样才能尽量减少受影响的缓存呢?

其实,上面两个问题是一个问题,那么,一致性哈希算法能够解决上述问题吗?

我们现在就来了解一下一致性哈希算法。

2、一致性hash算法的基本概念

​ 其实,一致性哈希算法也是使用取模的方法,只是,刚才描述的取模法是对服务器的数量进行取模,而一致性哈希算法是对2^32取模,什么意思呢?我们慢慢聊。

​ 首先,我们把二的三十二次方想象成一个圆,就像钟表一样,钟表的圆可以理解成由60个点组成的圆,而此处我们把这个圆想象成由2^32个点组成的圆,示意图如下:

在这里插入图片描述

​ 圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、5、6……直到232-1,也就是说0点左侧的第一个点代表232-1 ,我们把这个由2的32次方个点组成的圆环称为hash环。

​ 那么,一致性哈希算法与上图中的圆环有什么关系呢?我们继续聊,仍然以之前描述的场景为例,假设我们有3台缓存服务器,服务器A、服务器B、服务器C,那么,在生产环境中,这三台服务器肯定有自己的IP地址,我们使用它们各自的IP地址进行哈希计算,使用哈希后的结果对2^32取模,可以使用如下公式示意。

hash(服务器A的IP地址) % 2^32

​ 通过上述公式算出的结果一定是一个0到232-1之间的一个整数,我们就用算出的这个整数,代表服务器A,既然这个整数肯定处于0到232-1之间,那么,上图中的hash环上必定有一个点与这个整数对应,而我们刚才已经说明,使用这个整数代表服务器A,那么,服务器A就可以映射到这个环上,用下图示意

在这里插入图片描述

​ 同理,服务器B与服务器C也可以通过相同的方法映射到上图中的hash环中

hash(服务器B的IP地址) % 2^32

hash(服务器C的IP地址) % 2^32

​ 通过上述方法,可以将服务器B与服务器C映射到上图中的hash环上,示意图如下

在这里插入图片描述

​ 假设3台服务器映射到hash环上以后如上图所示(当然,这是理想的情况,我们慢慢聊)。

​ 好了,到目前为止,我们已经把缓存服务器与hash环联系在了一起,我们通过上述方法,把缓存服务器映射到了hash环上,那么使用同样的方法,我们也可以将需要缓存的对象映射到hash环上。

	假设,我们需要使用缓存服务器缓存图片,而且我们仍然使用图片的名称作为找到图片的key,那么我们使用如下公式可以将图片映射到上图中的hash环上。

hash(图片名称) % 2^32

​ 映射后的示意图如下,下图中的橘黄色圆形表示图片

在这里插入图片描述

​ 好了,现在服务器与图片都被映射到了hash环上,那么上图中的这个图片到底应该被缓存到哪一台服务器上呢?上图中的图片将会被缓存到服务器A上,为什么呢?因为从图片的位置开始,沿顺时针方向遇到的第一个服务器就是A服务器,所以,上图中的图片将会被缓存到服务器A上,如下图所示。

在这里插入图片描述

​ 没错,一致性哈希算法就是通过这种方法,判断一个对象应该被缓存到哪台服务器上的,将缓存服务器与被缓存对象都映射到hash环上以后,从被缓存对象的位置出发,沿顺时针方向遇到的第一个服务器,就是当前对象将要缓存于的服务器,由于被缓存对象与服务器hash后的值是固定的,所以,在服务器不变的情况下,一张图片必定会被缓存到固定的服务器上,那么,当下次想要访问这张图片时,只要再次使用相同的算法进行计算,即可算出这个图片被缓存在哪个服务器上,直接去对应的服务器查找对应的图片即可。

​ 刚才的示例只使用了一张图片进行演示,假设有四张图片需要缓存,示意图如下
在这里插入图片描述

​ 1号、2号图片将会被缓存到服务器A上,3号图片将会被缓存到服务器B上,4号图片将会被缓存到服务器C上。

3、一致性哈希算法的优点

​ 经过上述描述,我想兄弟你应该已经明白了一致性哈希算法的原理了,但是话说回来,一致性哈希算法能够解决之前出现的问题吗,我们说过,如果简单的对服务器数量进行取模,那么当服务器数量发生变化时,会产生缓存的雪崩,从而很有可能导致系统崩溃,那么使用一致性哈希算法,能够避免这个问题吗?我们来模拟一遍,即可得到答案。

​ 假设,服务器B出现了故障,我们现在需要将服务器B移除,那么,我们将上图中的服务器B从hash环上移除即可,移除服务器B以后示意图如下。

在这里插入图片描述

​ 在服务器B未移除时,图片3应该被缓存到服务器B中,可是当服务器B移除以后,按照之前描述的一致性哈希算法的规则,图片3应该被缓存到服务器C中,因为从图片3的位置出发,沿顺时针方向遇到的第一个缓存服务器节点就是服务器C,也就是说,如果服务器B出现故障被移除时,图片3的缓存位置会发生改变

在这里插入图片描述

​ 但是,图片4仍然会被缓存到服务器C中,图片1与图片2仍然会被缓存到服务器A中,这与服务器B移除之前并没有任何区别,这就是一致性哈希算法的优点,如果使用之前的hash算法,服务器数量发生改变时,所有服务器的所有缓存在同一时间失效了,而使用一致性哈希算法时,服务器的数量如果发生改变,并不是所有缓存都会失效,而是只有部分缓存会失效,前端的缓存仍然能分担整个系统的压力,而不至于所有压力都在同一时间集中到后端服务器上。

​ 这就是一致性哈希算法所体现出的优点。

4、哈希环的偏斜

​ 在介绍一致性哈希的概念时,我们理想化的将3台服务器均匀的映射到了hash环上,如下图所示
在这里插入图片描述

​ 在实际的映射中,服务器可能会被映射成如下模样。
在这里插入图片描述

​ 聪明如你一定想到了,如果服务器被映射成上图中的模样,那么被缓存的对象很有可能大部分集中缓存在某一台服务器上,如下图所示。

在这里插入图片描述

​ 上图中,1号、2号、3号、4号、6号图片均被缓存在了服务器A上,只有5号图片被缓存在了服务器B上,服务器C上甚至没有缓存任何图片,如果出现上图中的情况,A、B、C三台服务器并没有被合理的平均的充分利用,缓存分布的极度不均匀,而且,如果此时服务器A出现故障,那么失效缓存的数量也将达到最大值,在极端情况下,仍然有可能引起系统的崩溃,上图中的情况则被称之为hash环的偏斜,那么,我们应该怎样防止hash环的偏斜呢?一致性hash算法中使用"虚拟节点"解决了这个问题,我们继续聊。

5、虚拟节点

​ 话接上文,由于我们只有3台服务器,当我们把服务器映射到hash环上的时候,很有可能出现hash环偏斜的情况,当hash环偏斜以后,缓存往往会极度不均衡的分布在各服务器上,聪明如你一定已经想到了,如果想要均衡的将缓存分布到3台服务器上,最好能让这3台服务器尽量多的、均匀的出现在hash环上,但是,真实的服务器资源只有3台,我们怎样凭空的让它们多起来呢,没错,就是凭空的让服务器节点多起来,既然没有多余的真正的物理服务器节点,我们就只能将现有的物理节点通过虚拟的方法复制出来,这些由实际节点虚拟复制而来的节点被称为"虚拟节点"。加入虚拟节点以后的hash环如下。

在这里插入图片描述

​ “虚拟节点"是"实际节点”(实际的物理服务器)在hash环上的复制品,一个实际节点可以对应多个虚拟节点。

​ 从上图可以看出,A、B、C三台服务器分别虚拟出了一个虚拟节点,当然,如果你需要,也可以虚拟出更多的虚拟节点。引入虚拟节点的概念后,缓存的分布就均衡多了,上图中,1号、3号图片被缓存在服务器A中,5号、4号图片被缓存在服务器B中,6号、2号图片被缓存在服务器C中,如果你还不放心,可以虚拟出更多的虚拟节点,以便减小hash环偏斜所带来的影响,虚拟节点越多,hash环上的节点就越多,缓存被均匀分布的概率就越大。

6、 总结

一致性hash就是服务器ip对2^32取模,形成一个闭环的员,数据照此方法取模,数据存放方式就是顺时针找到的第一个服务器,如果服务器宕机,则数据会重新找顺时针找到的第一个服务器,对其他原来存在的数据不会产生影响,如果增加机器,则先从顺时针找的第一个服务器找,找不到找第二个!产生问题:数据倾斜:导致一个服务器承受的压力太大,所以就产生了一个虚拟节点的概念,目的就是让数据相对均匀的分布

11.2 实现方式

实现方式:一致性hash分片,利用一个分片节点对应一个或者多个虚拟hash桶的思想,,尽可能减少分片扩展时的数据迁移。
优点:有效解决了分布式数据库的扩容问题。
缺点:在横向扩展的时候,需要迁移部分数据;由于虚拟桶倍数与分片节点数都必须是正整数,而且要服从"虚拟桶倍数×分片节点数=设计极限",因此在横向扩容的过程中,增加分片节点并不是一台一台地加上去的,而是以一种因式分解的方式增加,因此有浪费物理计算力的可能性。

11.3 修改schema.xml文件

 <table name="user10" dataNode="dn1,dn2,dn3" primaryKey="id" rule="sharding-by-murmur" />

11.4 修改rule.xml文件

<tableRule name="sharding-by-murmur">
<rule>
<columns>id</columns>
<algorithm>murmur</algorithm>
</rule>
</tableRule>
<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>

11.5 重启mycat

11.6 创建mycat表

create table user10(id bigint not null primary key,name varchar(20));
insert into user10(id,name) values(1111111,database());
insert into user10(id,name) values(2222222,database());
insert into user10(id,name) values(3333333,database());
insert into user10(id,name) values(4444444,database());
insert into user10(id,name) values(8960000,database());

12 mysql 分片join

12.1 全局表

就是增加冗余表,避免分片join

​ 在分片的情况下,当业务表因为规模而进行分片之后,业务表与这个字典表的之间关联会变得比较棘手,因此,在mycat中存在一种全局表,他具备以下特性:

​ 1、全局表的插入、更新操作会实时的在所有节点上执行,保持各个分片的数据一致性

​ 2、全局表的查询操作,只从一个节点获取

​ 3、全局表可以跟任何一个表进行join操作

​ 实际操作:

​ 1、修改schema.xml文件

<table name="dict_order_type" dataNode="dn1,dn2" type="global"></table>

​ 2、向node03,node01添加dict_order_type表

​ 3、重启mycat

​ 4、向表中插入数据

INSERT INTO dict_order_type(id,order_type) VALUES(101,'type1');
INSERT INTO dict_order_type(id,order_type) VALUES(102,'type2');

​ 5、在各个节点进行数据查询,发现都能查询到对应的结果。

12.2mycat ER表的分片

ER表分片的意义就是提前将要进行管理的两个表放在同一个分片位置,
避免跨分片join

​ 在mycat中,我们已经将orders进行了数据分片,但是orders表跟orders_detail发生关联,如果只把orders_detail放到一个分片上,那么跨库的join很麻烦,所以提出了ER关系的表分片。什么意思呢?就是通过关联关系,将子表与父表关联的记录放在同一个数据分片上。

​ 1、修改schema.xml文件

		<table name ="orders" dataNode="dn1,dn2" rule="mod_rule">
			<childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />		</table>

​ 2、在node03上创建orders_detail表

​ 3、重启mycat

​ 4、插入数据

INSERT INTO orders_detail(id,detail,order_id) values(1,'detail1',1);
INSERT INTO orders_detail(id,detail,order_id) VALUES(2,'detail1',2);
INSERT INTO orders_detail(id,detail,order_id) VALUES(3,'detail1',3);
INSERT INTO orders_detail(id,detail,order_id) VALUES(4,'detail1',4);
INSERT INTO orders_detail(id,detail,order_id) VALUES(5,'detail1',5);
INSERT INTO orders_detail(id,detail,order_id) VALUES(6,'detail1',6);

12.2.1 效果

在这里插入图片描述
在这里插入图片描述

12.3、mycat的分片join

​ Join绝对是关系型数据库中最常用的一个特性,然而在分布式环境中,跨分片的join却是最复杂的,最难解决的一个问题。

​ 性能建议:

​ 1、尽量避免使用left join或right join,而用inner join

​ 2、在使用left join或right join时,on会优先执行,where条件在最后执行,所以再使用过程中,条件尽可能的在on语句中判断,减少where的执行

​ 3、少使用子查询,而用join

​ mycat目前版本支持跨分配的join,主要有四种实现方式

​ 1、全局表

​ 2、ER分片

​ 3、catletT(人工智能)

​ 4、ShareJoin

​ 全局表和ER分片在之前的操作中已经讲过了,此处不再赘述,下面详细讲解下另外两种方式。

Share join

​ ShareJoin是一个简单的跨分片join,基于HBT的方式实现。目前支持2个表的join,原理是解析SQL语句,拆分成单表的SQL语句执行,然后把各个节点的数据汇集。

​ 配置方式如下:

​ A,B的dataNode相同

<table name="A" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
<table name="B" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

​ A,B的dataNode不同

<table name="A" dataNode="dn1,dn2 " rule="auto-sharding-long" />
<table name="B" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
------------
<table name="A" dataNode="dn1 " rule="auto-sharding-long" />
<table name="B" dataNode=" dn2,dn3" rule="auto-sharding-long" />

​ 修改schema.xml

<table name="company" primaryKey="id" dataNode="dn1,dn2,dn3" rule="mod-long" />
<table name="customers" primaryKey="id" dataNode="dn1,dn2" rule="sharding-by-intfile"/>

​ 修改rule.xml

        <tableRule name="mod-long">
                <rule>
                        <columns>id</columns>
                        <algorithm>mod-long</algorithm>
                </rule>
        </tableRule>
        <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
                <!-- how many data nodes -->
                <property name="count">3</property>
        </function>
        <tableRule name="sharding-by-intfile">
                <rule>
                        <columns>sharding_id</columns>
                        <algorithm>hash-int</algorithm>
                </rule>
        </tableRule>
        <function name="hash-int"
                          class="io.mycat.route.function.PartitionByFileMap">
                <property name="mapFile">partition-hash-int.txt</property>
        </function>

​ 修改partition-hash-int.txt文件

10000=0
10010=1

​ sql语句:

create table company(id int primary key,name varchar(10)) engine=innodb;
insert company (id,name) values(1,'mycat');
insert company (id,name) values(2,'ibm');
insert company (id,name) values(3,'hp');

create table customers(id int not null primary key,name varchar(100),company_id int not null,sharding_id int not null);
insert into customers(id,name,company_id,sharding_id)values(1,'wang',1,10000),(2,'xue',2,10010),(3,'feng',3,10000);

​ 验证:

-- 可以看到有时可以查出对应的结果,有时则查询不到
select a.*,b.ID,b.NAME as tit from customers a,company b where a.COMPANY_ID=b.ID;
--可以看到每次都可以直接查询到结果
/*!mycat:catlet=io.mycat.catlets.ShareJoin */select a.*,b.ID,b.NAME as tit from customers a,company b where a.COMPANY_ID=b.ID;
--其他写法
/*!mycat:catlet=io.mycat.catlets.ShareJoin */select a.*,b.ID,b.NAME as tit from customers a join company b on a.COMPANY_ID=b.ID;
/*!mycat:catlet=io.mycat.catlets.ShareJoin */select a.*,b.ID,b.NAME as tit from customers a join company b where a.COMPANY_ID=b.ID;

13 全局序列号

在实现分库分表的情况下,数据库自增主键已经无法保证自增主键的全局唯一,为此,mycat提供了全局sequence,并且提供了包含本地配置和数据库配置等多种实现方式。

13.1 本地文件

使用此方式的时候,mycat讲sequence配置到文件中,当使用到sequence中的配置,mycat会更新sequence_conf.properties文件中sequence当前的值。

13.1.1 配置方式

在 sequence_conf.properties 文件中做如下配置:

GLOBAL_SEQ.HISIDS=
GLOBAL_SEQ.MINID=10001
GLOBAL_SEQ.MAXID=20000
GLOBAL_SEQ.CURID=10000

== 其中 HISIDS 表示使用过的历史分段(一般无特殊需要可不配置), MINID 表示最小 ID 值, MAXID 表示最大ID 值, CURID 表示当前 ID 值==
server.xml 中配置:

<system><property name="sequnceHandlerType">0</property></system>

注: sequnceHandlerType 需要配置为 0,表示使用本地文件方式。

13.1.2重启mycat

13.1.3 插入数据库

create table tab1(id int primary key,name varchar(10));
insert into tab1(id,name) values(next value for mycatseq_global,'test1');
insert into tab1(id,name) values(next value for mycatseq_global,'test2');
insert into tab1(id,name) values(next value for mycatseq_global,'test3');

缺点:当mycat重新发布后,配置文件中的sequence会恢复到初始值
优点:本地加载,读取速度较快

13.2数据库方式

​ 在数据库中建立一张表,存放sequence名称(name),sequence当前值(current_value),步长(increment int类型,每次读取多少个sequence,假设为K)等信息;

获取数据步骤

​ 1、当初次使用该sequence时,根据传入的sequence名称,从数据库这张表中读取current_value和increment到mycat中,并将数据库中的current_value设置为原current_value值+increment值。

​ 2、mycat将读取到current_value+increment作为本次要使用的sequence值,下次使用时,自动加1,当使用increment次后,执行步骤1中的操作

​ 3、mycat负责维护这张表,用到哪些sequence,只需要在这张表中插入一条记录即可,若某次读取的sequence没有用完,系统就停掉了,则这次读取的sequence剩余值不会再使用

配置方式:

​ 1、修改server.xml文件

<system><property name="sequnceHandlerType">1</property></system>

​ 2、修改schema.xml文件

<table name="test" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2,dn3" rule="mod-long"/>
<table name="mycat_sequence" primaryKey="name" dataNode="dn2"/>

​ 3、修改mycat配置文件sequence_db_conf.properties,添加属性值

#sequence stored in datanode
GLOBAL=dn1
COMPANY=dn1
CUSTOMER=dn1
ORDERS=dn1
MYCAT=dn2

​ 4、在dn2上添加mycat_sequence表

DROP TABLE IF EXISTS mycat_sequence;
CREATE TABLE mycat_sequence (name VARCHAR(50) NOT NULL,current_value INT NOT NULL,increment INT NOT NULL DEFAULT 100, PRIMARY KEY(name)) ENGINE=InnoDB;

​ 5、在dn2上的mycat_sequence表中插入初始记录

INSERT INTO mycat_sequence(name,current_value,increment) VALUES ('mycat', -99, 100);

​ 6、在dn2上创建函数

--创建函数
DROP FUNCTION IF EXISTS mycat_seq_currval;
DELIMITER $
CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50)) RETURNS varchar(64)     CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE retval VARCHAR(64);
SET retval="-999999999,null";
SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR)) INTO retval FROM mycat_sequence WHERE name = seq_name;
RETURN retval;
END $
DELIMITER ;
--设置sequence值
DROP FUNCTION IF EXISTS mycat_seq_setval;
DELIMITER $
CREATE FUNCTION mycat_seq_setval(seq_name VARCHAR(50),value INTEGER) RETURNS     varchar(64) CHARSET utf8
DETERMINISTIC
BEGIN
UPDATE mycat_sequence
SET current_value = value
WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END $
DELIMITER ;
--获取下一个sequence值
DROP FUNCTION IF EXISTS mycat_seq_nextval;
DELIMITER $
CREATE FUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS varchar(64)     CHARSET utf8
DETERMINISTIC
BEGIN
UPDATE mycat_sequence
SET current_value = current_value + increment WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END $
DELIMITER ;

数据测试:

​ 1、插入数据表

create table test(id int,name varchar(10));

​ 2、查询对应的序列数据表

SELECT * FROM mycat_sequence;

​ 3、向表中插入数据,可以多执行几次

insert into test(id,name) values(next value for MYCATSEQ_MYCAT,(select database()));

​ 4、查询添加的数据

SELECT * FROM test order by id asc;

​ 5、重新启动mycat,重新添加数据,查看结果,重启之后从101开始

SELECT * FROM mycat_sequence;

​ 6、重新查询数据表test

SELECT * FROM test order by id asc;

​ 大家在使用的时候会发现报错的情况,这个错误的原因不是因为我们的配置,是因为我们的版本问题,简单替换下版本即可。

mysql> insert into test(id,name) values(next value for MYCATSEQ_MYCAT,(select database()));
ERROR 1003 (HY000): mycat sequnce err.java.lang.NumberFormatException: null

13.3、本地时间戳方式

​ ID= 64 位二进制 (42(毫秒)+5(机器 ID)+5(业务编码)+12(重复累加)。

​ 换算成十进制为 18 位数的 long 类型,每毫秒可以并发 12 位二进制的累加。

使用方式:

​ 1、配置server.xml文件

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

​ 2、修改sequence_time_conf.properties

WORKID=06 #任意整数
DATAACENTERID=06  #任意整数

​ 3、修改schema.xml文件

<table name="test2" dataNode="dn1,dn2,dn3" primaryKey="id" autoIncrement="true" rule="mod-long" />

​ 4、启动mycat,并且创建表进行测试

create table test2(id bigint auto_increment primary key,xm varchar(32));
insert into test2(id,xm) values(next value for MYCATSEQ_GLOBAL,'lisi') ; 

​ 此方式的优点是配置简单,但是缺点也很明显就是18位的id太长,需要耗费多余的存储空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值