Mycat(水平拆分--分表 全局序列)

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

1、本地文件

此方式 mycat 将sequence 配置到文件中,当使用到 sequence 中的配置后, Mycat 会更下 classpath 中的 sequence_conf.properties 文件中的sequence当前的值。

  • 优点:本地加载,读取速度较快

  • 缺点:抗风险能力差, Mycat所在宿主机宕机后,无法读取本地文件。

2.数据库方式

原理:在数据库中建立一张表(表名MYCAT_SEQUENCE),存放 sequence 名称(name),sequence 当前值(current_value),步长(increment,每次读取多少个 sequence)等信息;

Sequence 获取步骤:

  • 当初次使用该 sequence 时,根据传入的 sequence 名称,从数据库这张表中读取 current_value,和increment (得到一个sequence号段)到 MyCat 中,并将数据库中的这张表的 current_value 设置为原 current_value 值+increment 值;

  • Mycat 将读取到 current_value+1 作为每次插入数据要使用的 sequence 值,当使用 increment 次后,执行上面步骤相同的操作;

  • 若Mycat某次读取的sequence号段还有一串值没有用完,系统就停掉了,则这次读取的 sequence 号段的剩余值不会再使用,没了就没了,只需保证每次插入数据的sequence值是唯一的;

切换到dn1数据库

创建表:

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;

为MYCAT_SEQUENCE表插入数据(序列名 起始值 步长):

INSERT INTO MYCAT_SEQUENCE(name,current_value,increment) VALUES (‘GLOBAL’, 100000,100); 

创建相应的函数一:传入序列名,获取当前sequence的值

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设定当前值(指定具体value)

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设定当前值(当前值=原当前值+步长)

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 ;

配置Mycat的/conf/sequence_db_conf.properties(指明所用的序列名,以及MYCAT_SEQUENCE表在哪个分片节点上)

GLOBAL=dn1

配置Mycat的/conf/server.xml,表示所用的全局序列方式为数据库方式

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

重启Mycat

INSERT INTO orders(id,amount,customer_id,order_type) VALUES(next value for MYCATSEQ_GLOBAL,1000,101,102);

此时在Mycat里select一下数据,可以看到插入的数据记录已经自动获取主键值

 

 

3.时间戳方式

全局序列 ID = 64 位 二进制 42(毫秒 )+ 5(机器 ID)+5(业务编码) + 12(重复累加)换算成十进制为 18 位数的 long 类型,每毫秒可以并发 12 位二进制的累加。

  • 优点:配置简单

  • 缺点:18位ID过长

     注:后续补上

4.自主生成全局序列

可以在java项目里自己生成全局序列,

  • 根据业务逻辑组合

  • 可以利用redis的单线程原子性 incr 来生成序列

    但,自主生成需要单独在工程中用java代码实现,还是推荐使用Mycat 自带全局序列

posted @ 2020-12-30 11:35  chenjiahao  阅读(336)  评论(0编辑  收藏  举报