mycat分片表全局自增主键测试

mycat分片表全局自增主键测试

一、全局序列号介绍

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

1.本地文件方式

使用服务器本地磁盘文件的方式

2.数据库方式

使用专用数据库的方式

3.本地时间戳方式

使用时间戳算法方式

4.分布式ZK ID 生成器

基于ZK 与本地配置的分布式ID 生成器(可以通过ZK 获取集群(机房)唯一InstanceID,也可以通过配置文
件配置InstanceID)

5.Zk 递增方式

另一种ZK生成方式

6.其他方式

二、配置方式详解

1.本地文件方式

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

# 这是全局表的设置
GLOBAL_SEQ.HISIDS=
GLOBAL_SEQ.MINID=1001
GLOBAL_SEQ.MAXID=1000000000
GLOBAL_SEQ.CURID=1000

# 下面是自定义表的设置

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

server.xml 中配置:

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

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

insert into table1(id,name) values(next value for MYCATSEQ_GLOBAL,‘test’);

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

[本地文件方式详细配置和测试]

1.1 修改配置文件server.xml,指定加密方式为本地文件方式

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

1.2 在schema.xml文件中配置,增加表tt,ID为主键,在dn$1-3上分片,分片方式mod-log

<table name="tt" primaryKey="id" autoIncrement="true" dataNode="dn$1-3" rule="mod-long"/>

1.3 修改sequence_conf.properties 文件中做如下配置:

# 这是全局表的设置
GLOBAL.HISIDS=
GLOBAL.MINID=10001
GLOBAL.MAXID=1000000000
GLOBAL.CURID=10000

# 下面是自定义表的设置
TT.HISIDS=
TT.MINID=1001
TT.MAXID=2000
TT.CURID=1000

1.4 建表tt

CREATE TABLE tt(
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name_` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

查看表结构

mysql> desc tt;                                      
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name_ | int(10) unsigned | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

查看表分片情况

mysql> explain select * from tt;
+-----------+--------------------------------+
| DATA_NODE | SQL                            |
+-----------+--------------------------------+
| dn1       | SELECT * FROM tt LIMIT 3000000 |
| dn2       | SELECT * FROM tt LIMIT 3000000 |
| dn3       | SELECT * FROM tt LIMIT 3000000 |
+-----------+--------------------------------+
3 rows in set (0.07 sec)

1.5 插入数据测试
插入一条使用全局序列号

insert into tt(id,name_) values(next value for MYCATSEQ_GLOBAL,1);

查看序列号使用

mysql> SELECT * FROM TT;
+-------+-------+
| id    | name_ |
+-------+-------+
| 10001 |     1 |
+-------+-------+
1 row in set (0.00 sec)

插入一条使用TT序列号

insert into tt(id,name_) values(next value for MYCATSEQ_TT,2);

查看序列好使用情况

mysql> SELECT * FROM TT ORDER BY name_;
+-------+-------+
| id    | name_ |
+-------+-------+
| 10001 |     1 |
|  1001 |     2 |
+-------+-------+
2 rows in set (0.01 sec)

多插入一些数据,查询结果

mysql> SELECT * FROM TT ORDER BY name_;                              
+-------+-------+
| id    | name_ |
+-------+-------+
| 10001 |     1 |
|  1001 |     2 |
|  1002 |     3 |
|  1003 |     4 |
|  1004 |     5 |
|  1005 |     6 |
+-------+-------+
6 rows in set (0.00 sec)

这些数据再分片上的情况

mysql (db1)>select * from tt;
+------+-------+
| id   | name_ |
+------+-------+
| 1002 |     3 |
| 1005 |     6 |
+------+-------+
2 rows in set (0.00 sec)

mysql (db2)>select * from tt;
+------+-------+
| id   | name_ |
+------+-------+
| 1003 |     4 |
+------+-------+
1 row in set (0.00 sec)

mysql (db3)>select * from tt;
+-------+-------+
| id    | name_ |
+-------+-------+
|  1001 |     2 |
|  1004 |     5 |
| 10001 |     1 |
+-------+-------+

OK It works!!

优点:配置简单,本地文件,读写速度快
缺点:导致MYCAT变成有状态的中间件,不利于部署集群
2.数据库方式
数据库方式存在比较明显的缺点,即MYCAT集群切换和保持序列的数据库主从切换之后,不可控内容较多
需要非常仔细的处理这些问题,维护成本较高,虽然实现MYCAT无状态,但有单点问题
3.本地时间戳方式

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

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

sequence_time_conf.properties

WORKID=0-31 任意整数
DATAACENTERID=0-31 任意整数

是个好方式

4.分布式ZK ID 生成器

-----最想测试的还是这个

配置选项:

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

原理说明:
Zk 的连接信息统一在myid.propertieszkURL 属性中配置。
基于ZK 与本地配置的分布式ID 生成器(可以通过ZK 获取集群(机房)唯一InstanceID,也可以通过配置文件配置InstanceID)ID 结构:long 64 位,ID 最大可占63 位

current time millis(微秒时间戳38 位,可以使用17 年)
instanceId(实例ID,可以通过ZK 或者配置文件获取,5 位,也就是十进制0-31)
threadId(线程ID,9 位)
increment(自增,6 位)
  • 一共63 位,可以承受单机房单机器单线程1000*(2^6)=640000 的并发。

  • 无悲观锁,无强竞争,吞吐量更高
    配置文件:sequence_distributed_conf.properties,只要配置里面:INSTANCEID=ZK 就是从ZK 上获取InstanceID

配置ZK ID生成器的主要步骤

4.1 配置zookeeper

zookeeper是hadoop的一个子项目
一般生产上需要配置zookeeper集群,奇数个节点,至少三个节点
为了测试mycat的相关特性,我们只搭建一个单节点的zookeeper

ZooKeeper Standalone模式

从Apache网站上(zookeeper.apache.org)下载ZooKeeper软件包,我选择了3.3.4版本的(zookeeper-3.3.4.tar.gz),在一台Linux机器上安装非常容易,只需要解压缩后,简单配置一下即可以启动ZooKeeper服务器进程。

将zookeeper-3.3.4/conf目录下面的 zoo_sample.cfg修改为zoo.cfg,配置文件内容如下所示:

tickTime=2000
dataDir=/home/hadoop/storage/zookeeper
clientPort=2181
initLimit=5
syncLimit=2

下面启动ZooKeeper服务器进程:

cd zookeeper-3.3.4/
bin/zkServer.sh start

这样zookeeper就可以使用了,防火墙的配置自行处理

ZooKeeper 分布式模式
搭建生产网络或夸机房分布式的时候再进行补充
4.2 配置mycat

主要涉及三个方面,修改myid.properties,修改server.xml,修改sequence_distributed_conf.properties

myid.properties:

loadZk=true                 #使用zk管理mycat和ID
zkURL=127.0.0.1:2181        #zk服务器的地址和端口
clusterId=010               #本机房mycat集群的ID
myid=01001                  #集群内mycat的ID
clusterNodes=mycat-02       #mycat节点的名称
#server  booster  ;   booster install on db same server,will reset all minCon to 1
#type=server
#boosterDataHosts=dn2,dn3

server.xml:

<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
    <system>
        <property name="defaultSqlParser">druidparser</property>
        <property name="useCompression">1</property>
        <property name="serverPort">3306</property>
        <property name="managerPort">3308</property>
        <property name="maxStringLiteralLength">65535</property>
        <!-- sequnceHandlerType 0:文件模式 1: 2:3:zookeeper分布式管理模式 -->
        <property name="sequnceHandlerType">3</property>
    </system>
    <user name="root">
        <property name="password">password</property>
        <property name="schemas">dbykt</property>
    </user>
</mycat:server>

sequence_distributed_conf.properties:

INSTANCEID=01
CLUSTERID=01

上面三个文件修改完成后,复制conf下的所有文件到 conf/zkconf/目录下

cp *.txt *.xml *.properties zkconf/

初始化:

cd ./bin/
./init_zk_data.sh
4.3 启动mycat

先使用console看看启动是否正常

./bin/mycat console

正常之后再进行启动

./bin/mycat start
4.4 测试mycat ZK 分布式ID生成器

使用工具Jmeter,此处不赘述

配置表ot1:

.....
<table name="ot1" dataNode="dn$1-20,dn$21-40,dn$41-60" rule="card_no" primaryKey="id" autoIncrement="true"/>
......

重启mycat

./bin/mycat restart

建表(因为同时测试了插入性能,所以表较为复杂)

CREATE TABLE `ot1` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
...............
...............

  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Jmeter 插入数据测试
使用的sql语句如下:

INSERT INTO `ot1` (
    `id`,
................
................
 

)
VALUES
    (
        next value for MYCATSEQ_OT,
...............
...............
 
    );

查询观察结果

mysql> SELECT id FROM ot1 ORDER BY id;

........

| 3894484648986705980 |
| 3894484648986705981 |
| 3894484649020260414 |
| 3894484649053814784 |
| 3894484649053814847 |
| 3894484649389359105 |
| 3894484649926230018 |
| 3894484649926230019 |
| 3894484649926230020 |
| 3894484649926230021 |
| 3894484649959784454 |
| 3894484649959784455 |
| 3894484649959784456 |
| 3894484649993338889 |
| 3894484649993338890 |
| 3894484650026893323 |
| 3894484650026893324 |
| 3894484650060447757 |
| 3894484650060447758 |
| 3894484650094002191 |
........

查询数据总量:

mysql> select count(id) id_count from ot1;
+----------+
| id_count |
+----------+
| 37784391 |
+----------+

查出最大ID:

mysql> select max(id) id from ot1 ;
+---------------------+
| id                  |
+---------------------+
| 3897338173617897525 |
+---------------------+
1 row in set (0.03 sec)

判断一下是否有重复ID:

mysql> select count(id),id from ot1 group by id having count(id)>1;

Empty set (1 min 42.85 sec)
4.5 结论

分布式ZK ID生成器,果然强大。这为数据库跨机房双活提供了新的方案,使得双A机房架构下的数据最终一致性有了新的思路。

时间: 2024-08-26 09:52:53

mycat分片表全局自增主键测试的相关文章

SQL Server数据库表重置自增主键号(通常是指ID)

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

mysql数据库表的自增主键号不规律,重新排列

mysql数据库表的自增主键ID乱了,需要重新排序. 原理:删除原有的自增ID,重新建立新的自增ID. 1.删除原有主键: ALTER TABLE `table_name` DROP `id`; 2.添加新主键字段: ALTER TABLE `table_name` ADD `id` MEDIUMINT( 8 ) NOT NULL FIRST; 3.设置新主键: ALTER TABLE `table_name` MODIFY COLUMN `id` MEDIUMINT( 8 ) NOT NULL

sql语句修改mysql表的自增主键

我们在开发过程中,会用到一些初始化语句,由于外键关系,我们需要把某一些ID写死,那么当我们初始化完毕后,需要将Mysql中的表的自增主键从某一个值开始递增. alter table `system_role_menu` AUTO_INCREMENT = 11; 上述表表示,system_role_menu表从11开始递增,下一个插入的值的主键为11.

如何获取数据表中自增主键的值

一.MySql数据库 当向数据库中插入一条数据的时候,默认是拿不到自增主键的值的, 需要设置如下两个属性才可以拿到主键值! 设置userGeneratedKeys属性值为true:使用自动增长的主键.使用keyProperty设置把主键值设置给哪一个属性 1 <insert id="addEmp" parameterType="com.neuedu.mybatis.bean.Employee" useGeneratedKeys="true"

Mysql数据库表的自增主键重新排列

1,删除原有主键:ALTER TABLE `表名` DROP `id`; 2,添加新主键字段:ALTER TABLE `表名` ADD `id` MEDIUMINT( 8 ) NOT NULL FIRST; 3,设置新主键:ALTER TABLE `表名` MODIFY COLUMN `id` MEDIUMINT( 8 ) NOT NULL AUTO_INCREMENT,ADD PRIMARY KEY(id);

分库分表之后,id 主键如何处理?

其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持.所以这都是你实际生产环境中必须考虑的问题. 基于数据库的实现方案 数据库自增 id 这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id.拿到这个 id 之后再往对应的分库分表里去写入. 这个方案的好处就是方便简单,谁都会用:缺点就是单库生成自增 id,要是高并

分库分表之后,id 主键如何处理

基于数据库的实现方案 数据库自增 id 这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id.拿到这个 id 之后再往对应的分库分表里去写入. 这个方案的好处就是方便简单,谁都会用:缺点就是单库生成自增 id,要是高并发的话,就会有瓶颈的:如果你硬是要改进一下,那么就专门开一个服务出来,这个服务每次就拿到当前 id 最大值,然后自己递增几个 id,一次性返回一批 id,然后再把当前最大 id 值修改成递增几个 id 之后的

面试官:分库分表之后,id 主键如何处理?

面试题 分库分表之后,id 主键如何处理? 面试官心理分析 其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持.所以这都是你实际生产环境中必须考虑的问题. 面试题剖析 数据库自增 id 这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id.拿到这个 id 之后再往对应的分库分表里去写入. 这个方案的好处就是方便简

分布式中的分库分表之后,ID 主键如何处理?

面试题 分库分表之后,id 主键如何处理?(唯一性,排序等) 面试官心理分析 其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持,排序问题等.所以这都是你实际生产环境中必须考虑的问题. 面试题剖析 基于数据库的实现方案 数据库自增 id 这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id.拿到这个 id 之后再