MyCat 分片之枚举规则(多租户)

myCat的一个重要功能就是数据库分片,允许你将一些规模较大的表分散到不同的数据库,来缓解数据库的压力,或者实现数据的隔离。

当然通过myCat来看,这些分片像是合起来的一张表,只是当sql到达myCat后,根据配置的分片规则,myCat去操作不同的数据库。

没有配置分片规则的表,需要配置为全局表,所有分片的数据是一样的。

如果没有配置分片规则,也没有配置为全局表,那么数据插入时所有分片插入,数据查询时所有分片都查出来,你有几个分片就会查出来几份数据。不过,你可以通过只给这个表配置一个数据节点,来达到既不分片也不全局的目的。

1.MyCat的基础配置

2.编写分片规则

  • 打开conf文件夹下的rule.xml文件,添加以下代码
    <!-- 分片规则,按租户分片 -->
    <tableRule name="sharding-by-tenant">
      <rule>
         <columns>tenant_id</columns>
         <algorithm>by-tenant</algorithm>
      </rule>
    </tableRule>



    <!-- 分片方法,按照sharding-by-tenant.txt文件进行枚举分片 -->
    <!-- type为分片字段的数据类型,1为字符串,0为int -->
    <!-- defaultNode配置是否使用默认节点,默认为0,表示不设置默认节点,这样会导致遇到不识别的枚举值时会报错,如果设置的值大于零,该值就是默认节点,会把不识别的枚举值分配到默认节点。 -->
    <function name="by-tenant" class="io.mycat.route.function.PartitionByFileMap">
        <property name="mapFile">sharding-by-tenant.txt</property>
        <property name="type">1</property>
        <property name="defaultNode">0</property>
    </function>

注意:mycat的配置文件,节点的顺序是有要求的,所有的tableRule要放在前面,所有的function要放在后面

  • conf文件夹下创建sharding-by-tenant.txt文件,内容如下
220=0
30=1

意思是tenant_id字段值为220时,走第一个dataNode,值为30时,走第二个dataNode。找不到对应分片时,默认走第一个。

3.给表配置分片规则

  • 打开schema.xml文件,为table配置分片规则
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<schema name="demo_db" checkSQLschema="false" sqlMaxLimit="100">
		<table name="sys_user" primaryKey="id" rule="sharding-by-tenant" dataNode="dn1,dn2" />
	</schema>
	
	<dataNode name="dn1" dataHost="dataHost220" database="demo_db" />
	<dataNode name="dn2" dataHost="dataHost30" database="demo_db" />
	<dataHost name="dataHost220" maxCon="1000" minCon="10" balance="3"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="192.168.3.220:3306" user="root" password="root">
			<readHost host="hostS2" url="192.168.3.220:3307" user="root" password="root" />
		</writeHost>
	</dataHost>
	<dataHost name="dataHost30" maxCon="1000" minCon="10" balance="3"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="192.168.3.30:3306" user="root" password="Root@123">
			<readHost host="hostS2" url="192.168.3.30:3307" user="root" password="Root@123" />
		</writeHost>
	</dataHost>

</mycat:schema>

4.测试分片

mycat的枚举分片,根据分片字段,来进行分片的,分片字段不能修改。

插入一条数据时,根据分片字段会将其插入相应的分片数据库。

查询数据时,如果查询语句的where语句中包含分片字段,则只会去查询相应的分片数据库(没有匹配的枚举型会查默认节点),否则全部节点都查询。

可以根据以上特性,测试分片是否成功。现在tenant_id=220存在dataNode1,tenant_id=30存在dataNode2,如果向dataNode1中插入一条tenant_id=30的数据。通过mycat查询,带上条件为tenant_id=30,应该是查不到刚才的数据的。

5.分布式自增长主键问题

像这样进行分片,每个分片都进行自增长主键,那么在mycat中就会发生主键冲突,那么最好有一个分布式的统一主键管理。

mycat也提供了多种的分布式自增长主键方式,我选择了我认为最合适的一种。

  • 在dn1的主库中,创建一个序列表。

像这个配置,mycat在启动时,会自动从表中,读取100条ID,用完了,再去读100条。这样即使你有多个mycat负载均衡,也不会出现主键冲突。

#所有操作都在 db1 上
#创建 MYCAT_SEQUENCE 表
DROP TABLE IF EXISTS MYCAT_SEQUENCE;
– name sequence 名称
– current_value 当前 value
– increment 增长步长!   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;

#插入一条 sequence
INSERT INTO MYCAT_SEQUENCE(name,current_value,increment) VALUES (‘SYS_USER’,
100, 100);

注意:表名MYCAT_SEQUENCE必须是大写。

注意:在dn1节点的从库的配置文件my.cnf中,添加以下代码,来忽略对序列表的同步。

replicate-ignore-table = demo_db.MYCAT_SEQUENCE
  • 在dn1的主库中,创建必须的方法
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8
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
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8
BEGIN
UPDATE MYCAT_SEQUENCE SET current_value = current_value + increment  WHERE NAME = seq_name;
RETURN mycat_seq_currval(seq_name);
END
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50),VALUE INTEGER) RETURNS varchar(64) CHARSET utf8
BEGIN
   UPDATE MYCAT_SEQUENCE SET current_value = VALUE    WHERE NAME = seq_name;
RETURN mycat_seq_currval(seq_name);
END
  • 在mycat的配置文件sequence_db_conf.properties中,添加以下代码
SYS_USER=dn1

这个“SYS_USER”即是序列表中name列的内容,也是表名。

  • 在mycat的配置文件schema.xml中,为表SYS_USER添加自增长配置
<schema name="demo_db" checkSQLschema="false" sqlMaxLimit="100">
	<table name="sys_user" primaryKey="id" rule="sharding-by-tenant" autoIncrement="true" dataNode="dn1,dn2" />
</schema>
  • 确保mycat的配置文件server.xml中,这一项值为1
<property name="sequnceHandlerType">1</property>

配置完成。

如果mycat启动不成功,请查看mycat/logs/wrapper.log日志

如果mycat启动后出现问题,或者功能出现问题,清查看mycat/logs/mycat.log日志

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值