资讯专栏INFORMATION COLUMN

Mycat的实践二:全局序列号

DesGemini / 1444人阅读

摘要:这里应该是的显示,配置成了时间戳序列方式了,显示的还是本地文件方式部分安装参考百度初始化插入等测试受影响的行时间总结我们在分布式的环境下,建议全局序列的顺序

上一节回顾 如果你还初识mycat,你可以阅读

Mycat的实践一:初始Mycat

遇到的问题
通过上一节的学习,我们遇到了一个insert无法插入的问题

我们思考一个问题,我们上一节在mysql上创建了3个分库,每个分库下每一个对应的表
CREATE TABLE `travelrecord` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(22) NOT NULL DEFAULT "",
  `time` int(10) unsigned NOT NULL DEFAULT "0",
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

这里的id是自增长,如果是在mycat的分布式下,肯定面临这一个id序列的增长问题。

如果我们各自在mysql端的三个库分别插入不同的数据,如:
use mycat-db1;
insert into travelrecord(name, time) values("test1", 0);
use mycat-db2;
insert into travelrecord(name, time) values("test1", 0);
use mycat-db3;
insert into travelrecord(name, time) values("test1", 0);

这里面临的每一个库下增长各自分离,所以可能不同db之间下的id可能会重复

mycat肯定要解决不同datahost下的datanode的结合后逻辑表下面的序列重复问题,所以插入就遇到了问题

接下去我们通过mycat的全局序列号解决插入的问题
Mycat 全局序列号 简介
在实现分库分表的情况下,数据库自增主键已无法保证自增主键的全局唯一。为此, MyCat 提供了全局sequence,并且提供了包含本地配置和数据库配置等多种实现方式
全局序列的三种方式
1. 本地文件
缺点:在mycat重启后,配置文件中sequence会恢复到初始值,造成下次操作序列重复
优点:本地加载,读取速度较快

2. 数据库
优点:在mycat重启后,sequence值不会被初始化
缺点:如果存取sequence的数据库挂了,会遇到单点故障

3. 时间
优点:不存在上面两种方案因为mycat的重启导致id重复的现象
缺点:数据类型太长,建议采用bigint(最大取值18446744073709551615)

4. zookeeper
建议采用,zookeeper自身解决单点和序列问题
本地方式 mycat conf/server.xml配置调整
0
查看配置是否生效
# 重启mycat
# 先停止 startup_nowrap.bat
bin/startup_nowrap.bat

我这边是通过navicat连接(command)
# mysql -uroot -p123456 -p 9066

show @@sysparam;

# output: 输出了本地文件方式,表示配置成功
...
| sequnceHandlerType            | 本地文件方式  | 指定使用Mycat全局序列的类型。|
...
插入数据
# 第一次尝试
insert into travelrecord(name) values("20180802 13:32");
# output: 提示错误了,提示了什么ID列没有提供
[SQL]insert into travelrecord(name) values("20180802 13:32");
[Err] 1064 - bad insert sql (sharding column:ID not provided,INSERT INTO travelrecord (name)
VALUES ("20180802 13:32")

# 第二次尝试
insert into travelrecord(id, name) values(next value for MYCATSEQ_GLOBAL, "20180802 13:32");
# output: 成功
受影响的行: 1
时间: 0.004s

不过这样写起来很麻烦,而且会改变现有业务里的代码,因为我们大部分之前的单机业务的代码是不会写id的,都是利用mysql的主键自增长
next value for MYCATSEQ_XXX 说明
是mycat用于分布式序列生成的的一种方式,在mycat里这个根据sequnceHandlerType的三种方式对应到不同的三个配置文件分别是:
sequence_conf.properties -> 本地
sequence_db_conf.properties -> mysql
sequence_time_conf.properties -> time
sequence_distributed_conf.properties -> zookeeper等分布式支持

上个测试我们使用了next value for MYCATSEQ_GLOBAL
打开sequence_conf.properties查看

COMPANY.MAXID=2000
GLOBAL.MAXID=20000
COMPANY.HISIDS=
CUSTOMER.MAXID=2000
HOTNEWS.CURID=1000
ORDER.MINID=1001
CUSTOMER.HISIDS=
HOTNEWS.MINID=1001
TRAVELRECORD.MAXID=2000000
GLOBAL.CURID=10003
ORDER.MAXID=2000
TRAVELRECORD.HISIDS=
COMPANY.CURID=1000
CUSTOMER.CURID=1000
COMPANY.MINID=1001
GLOBAL.MINID=10001
HOTNEWS.MAXID=2000
CUSTOMER.MINID=1001
TRAVELRECORD.CURID=506
GLOBAL.HISIDS=
HOTNEWS.HISIDS=
ORDER.CURID=1000
TRAVELRECORD.MINID=5001
ORDER.HISIDS=

# 查看我们之前插入的数据:
select * from travelrecord;
...
| 10002 | 20180802 13:32 |    0 |
...
我们看到id插入是10002,自增长来自GLOBAL.CURID
自增长式插入
# schema.xml里的配置增加2个属性, mycat会根据表自动获取到sequence配置里的属性
# 
# mycat重启

insert into travelrecord(name) values("20180802 13:49");
# output: 成功
受影响的行: 1
时间: 0.004s

# 查看我们之前插入的数据:
select * from travelrecord;
...
|   507 | 20180802 13:49 |    0 |
...
我们看到id插入是507,自增长来自TRAVELRECORD.CURID数据库方式mycat conf/server.xml配置调整
1
查看配置是否生效
同上不重复了

| sequnceHandlerType            | 数据库方式    | 指定使用Mycat全局序列的类型。|
sql
# 序列表
CREATE TABLE `mycat_sequence` (
  `name` varchar(50) NOT NULL,
  `current_value` int(11) NOT NULL,
  `increment` int(11) NOT NULL DEFAULT "1",
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# mycat_seq_currval函数
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

# mycat_seq_nextval函数
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

# mycat_seq_setval函数
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

# test
select mycat_seq_currval("TRAVELRECORD");
# output: 800,1
插入一条记录
INSERT INTO `mycat-db1`.`mycat_sequence` (`name`, `current_value`, `increment`) VALUES ("TRAVELRECORD", "800", "1");
插入数据测试
insert into travelrecord(name) values("20180802 14:18");
# output: 成功
受影响的行: 1
时间: 0.004s

# 查看我们之前插入的数据:
select * from travelrecord;
...
|   801 | 20180802 14:18 |    0 |
...
我们看到id插入是801,自增长来自数据表,查看数据库表, 并自动修改表的当前记录+1(我们的increment=1)

# 切换到真实的mycat-db1
select * from mycat_sequence;
| TRAVELRECORD |           801 |         1 |
时间方式mycat conf/server.xml配置调整
2
查看配置是否生效
同上不重复了

| sequnceHandlerType            | 本地文件方式  | 指定使用Mycat全局序列的类型。 |

# 这里应该是mycat的显示bug,配置成了时间戳序列方式了,显示的还是本地文件方式
插入等测试
select next value for MYCATSEQ_GLOBAL;
# 1024911601620357120

select next value for MYCATSEQ_GLOBAL;
# 1024911649208930304

insert into travelrecord(name) values("20180808 14:56")
#output: 
[Err] 1064 - can"t find any valid datanode :TRAVELRECORD -> ID -> 1024911922555916288
# 上面的出错,是因为我们的表插入的路由方式是rule="auto-sharding-long",找不到这么多的序列对应的datanode
# 调整 rule="mod-long",并修改三个真实分库的id未bigint(20) 并重启mycat


insert into travelrecord(name) values("20180808 15:01");
# 受影响的行: 1
# 时间: 0.048s


select * from travelrecord;
...
| 1024910441362624512 | 20180802 14:51 |    0 |
...
分布式方式(zookeeper)mycat conf/server.xml配置调整
3
查看配置是否生效
同上不重复了

| sequnceHandlerType            | 本地文件方式  | 指定使用Mycat全局序列的类型。 |

# 这里应该是mycat的显示bug,配置成了时间戳序列方式了,显示的还是本地文件方式
zookpeeper部分
安装参考百度
myid.properties:
loadZk=true
zkURL=127.0.0.1:2181
clusterId=mycat-cluster-1
myid=mycat_fz_01
clusterNodes=mycat_fz_01,mycat_fz_02,mycat_fz_04
#server  booster  ;   booster install on db same server,will reset all minCon to 1
type=server
boosterDataHosts=localhost1
初始化mycat zk
bin/init_zk_data.cmd
插入等测试
select next value for MYCATSEQ_GLOBAL;
# 5328679401562341409
select next value for MYCATSEQ_GLOBAL;
# 5328680350783668258

insert into travelrecord(name) values("20180808 15:58");
# 受影响的行: 1
# 时间: 0.048s


select * from travelrecord;
...
| 5328681411405709347 | 20180808 15:58 |    0 |
...
总结
我们在mycat分布式的环境下,建议全局序列id的顺序: zookeeper > mysql > timestamp(SnowFlake) > localfile

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29158.html

相关文章

  • Mycat实践一:初始Mycat

    摘要:通过完成可视化配置,及智能监控,自动运维。通过本地节点,完整的解决数据扩容难度,实现自动扩容机制,解决扩容难点。支持基于的主从切换及集群化管理。通过智能优化,分析分片热点,提供合理的分片建议,索引建议,及数据切分实时业务建议。 Mycat Mycat简介 1. 一个彻底开源的,面向企业应用开发的大数据库集群 2. 支持事务、ACID、可以替代MySQL的加强版数据库 3. 一个可以视为...

    Paul_King 评论0 收藏0
  • MyCat简单使用与配置

    基本配置 1 . 在mycat/conf目录下,MyCat核心配置文件:schema.xml select user() ...

    CoderStudy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<