当前位置: 首页 > 后端技术 > PHP

Mycat的练习2:全局序列号

时间:2023-03-29 15:08:05 PHP

上一节的回顾如果你还是mycat的新手,可以看一下Mycat的练习1:初始Mycat遇到的问题通过上一节的学习,我们遇到了一个insert无法插入让我们考虑一个问题。上一节我们在mysql上创建了3个分库,每个分库下分别对应一张表CREATETABLE`travelrecord`(`id`int(10)unsignedNOTNULLAUTO_INCREMENT,`name`varchar(22)NOTNULLDEFAULT'',`time`int(10)unsignedNOTNULLDEFAULT'0',PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8mb4;其中id是自增长的,如果在mycat的分布下,肯定会面临这个id序列的增长问题。如果我们分别在mysql端的三个数据库中插入不同的数据,比如:usemycat-db1;insertintotravelrecord(name,time)values('test1',0);usemycat-db2;insertintotravelrecord(name,time)values('test1',0);usemycat-db3;insertintotravelrecord(name,time)values('test1',0);这里面对的各个库的增长是分开的,所以db之间可能不一样,下面的id可能会重复。mycat必须解决不同datahost下的datanode合并后逻辑表下的序列重复问题,所以插入遇到了问题。接下来我们通过mycat的全局序号来解决插入问题。Mycat全局序号介绍在分库分表实现的情况下,数据库自增主键已经不能保证自增主键的全局唯一性了。为此,MyCat提供了一个全局序列,并提供了全局序列的三种方法,包括本地配置和数据库配置。导致下一个操作序列重复。优点:本地加载,读取速度更快2.数据库优点:重启mycat后不会初始化序列值缺点:如果访问序列的数据库挂了,会遇到单点故障3。时间优势:没有上面两种方案因为mycat重启导致的id重复缺点:数据类型太长,建议使用bigint(最大值18446744073709551615)4.建议使用zookeeper,zookeeper自己解决single-本地点和序列问题方法mycatconf/server.xml配置调整0查看配置是否生效#restartmycat#stopstartup_nowrap.batbin/startup_nowrap.bat我在这里通过navicat连接(命令)#mysql-uroot-p123456-p9066show@@sysparam;#output:本地文件方式输出,说明配置成功...|序列处理程序类型|本地文件模式|指定Mycat全局序列的类型。|...插入数据#第一次尝试insertintotravelrecord(name)values('2018080213:32');#输出:提示错误,提示未提供ID列[SQL]insertintotravelrecord(name)values('2018080213:32');[Err]1064-错误的插入sql(分片列:未提供ID,INSERTINTOtravelrecord(name)VALUES('2018080213:32')#第二次尝试插入travelrecord(id,name)values(nextvalueforMYCATSEQ_GLOBAL,'2018080213:32');#output:Success影响行数:1Time:0.004s但是这样写起来很麻烦,而且会改动现有业务中的代码,因为我们之前的单机业务代码大多不知道id怎么写,所以都是使用mysql的主键为MYCATSEQ_XXX自增next值,说明这是mycat生成分布式序列的一种方式。在mycat中,这是基于sequnceHandlerType的三个方法对应三个不同的配置文件:sequence_conf.properties->localsequence_db_conf.properties->mysqlsequence_time_conf.properties->timesequence_distributed_conf.properties->zookeeper和其他分布式支持上次测试我们为MYCATSEQ_GLOBAL使用next值打开sequence_conf.properties查看COMPANY.MAXID=2000GLOBAL.MAXID=20000COMPANY.HISIDS=CUSTOMER.MAXID=2000HOTNEWS.CURID=1000ORDER.MINID=1001CUSTOMER.HISIDS=HOTNEWS.MINID=1001TRAVELRECORD.MAXID=2000000GLOBAL.CURID=10003ORDER.MAXID=2000TRAVELRECORD.HISIDS=COMPANY.CURID=1000CUSTOMER.CURID=1000COMPANY.MINID=1001GLOBAL.MINID=10001HOTNEWS.MAXID=2000CUSTOMER.MINID=1001TRAVELSIDSHORD6.CURID=1001TRAVELSIDSHORD0.CURID=1000COMPANY.MINID=1001GLOBAL.MINID=10001HOTNEWS.MAXID=ORDER.CURID=1000TRAVELRECORD.MINID=5001ORDER.HISIDS=#查看我们之前插入的数据:select*fromtravelrecord;...|10002|2018080213:32|0|...我们看到插入的id是10002,自增长来自GLOBAL.CURID自增长插入#schema.xml中的配置增加了2个属性,mycat会根据顺序配置自动获取属性表##mycatrestartinsertintotravelrecord(name)values('2018080213:49');#output:Successfulaffectedrows:1time:0.004s#查看我们之前插入的数据:select*fromtravelrecord;...|507|2018080213:49|0|...我们看到id插入是507,自增长来自TRAVELRECORD.CURID数据库方法mycatconf/server.xml配置调整1查看配置是否有效同上不再重复|序列处理程序类型|数据库方法|指定Mycat全局序列的类型|sql#顺序表CREATETABLE`mycat_sequence`(`name`varchar(50)NOTNULL,`current_value`int(11)NOTNULL,`increment`int(11)NOTNULLDEFAULT'1',PRIMARYKEY(`name`))ENGINE=InnoDBDEFAULTCHARSET=utf8;#mycat_seq_currval函数CREATEFUNCTION`mycat_seq_currval`(seq_nameVARCHAR(50))RETURNSvarchar(64)CHARSETutf8DETERMINISTICBEGINDECLAREretvalVARCHAR(64);SETretval="-99999null"9;99,SELECTCONCAT(CAST(current_valueASCHAR),",",CAST(incrementASCHAR))INTOretvalFROMMYCAT_SEQUENCEWHERENAME=seq_name;RETURNretval;END#mycat_seq_nextval函数创建函数`mycat_seq_nextval`(seq_nameVARCHAR(50))RETURNSvarchar(64)CHARSETutf8DETERMINISTICBEGINUPDATEMYCAT_SEQUENCESETcurrent_value=current_value+incrementWHERENAME=seq_name;RETURNmycat_seq_currval(seq_name);END#mycat_seq_setval函数创建函数`mycat_seq_setval`(seq_nameVARCHAR(50),VALUEINTEGERva)返回rchar(64)CHARSETutf8DETERMINISTICBEGINUPDATEMYCAT_SEQUENCESETcurrent_value=VALUEWHERENAME=seq_name;RETURNmycat_seq_currval(seq_name);END#testselectmycat_seq_currval('TRAVELRECORD');#INcat1INT`插入记录.`mycat_sequence`(`name`,`current_value`,`increment`)VALUES('TRAVELRECORD','800','1');insertdatatestinsertintotravelrecord(name)values('2018080214:18');#output:SuccessAffectedrows:1Time:0.004s#查看我们之前插入的数据:select*fromtravelrecord;...|801|2018080214:18|0|...我们看到id插入是801,自增长来自于数据表,查看数据库表,自动修改表的当前记录+1(我们的increment=1)#切换到真正的mycat-db1从mycat_sequence中选择*;|旅行记录|801|1|timemodemycatconf/server.xml配置调整2查看配置是否生效不再赘述|序列处理程序类型|本地文件法|指定Mycat全局序列的类型|#这应该是mycat的显示bug。配置为时间戳顺序方式,显示仍然是本地文件插入测试。'2018080814:56')#output:[Err]1064-can'tfindanyvaliddatanode:TRAVELRECORD->ID->1024911922555916288#上面的错误是因为我们插入表的路由方式是rule="auto-sharding-long",找不到那么多sequences对应的datanode#调整rule="mod-long",修改三个真实分库的id不是bigint(20)重启mycatinsertintotravelrecord(name)values('2018080815:01');#受影响的行数:1#时间:0.048sselect*fromtravelrecord;...|1024910441362624512|2018080214:51|0|...分布式模式(zookeeper)mycatconf/server。xml配置调整3查看配置是否生效不再赘述|序列处理程序类型|本地文件法|指定Mycat全局序列的类型。|#这个应该是mycat的显示bug。配置为时间戳序列方式,显示仍然是本地文件方式。安装了zoopeer部分。参考百度myid.properties:loadZk=truezkURL=127.0.0.1:2181clusterId=mycat-cluster-1myid=mycat_fz_01clusterNodes=mycat_fz_01,mycat_fz_02,mycat_fz_04#serverbooster;Booster在DB同一服务器上安装,将将所有MinCon重置为1Type=ServerBoosterDataHosts=localHost1初始化MyCatZkbin/init_zk_data.cmd插入选择MyCatseq_global的下一个值选择下一个值2018080815:58');#受影响的行:1#时间:0.048sselect*fromtravelrecord;...|5328681411405709347|20180808|09:58综上所述,在mycat分布式环境下,推荐全局sequenceids的顺序:zookeeper>mysql>timestamp(SnowFlake)>localfile