Mycat(二)——分布式ID生成策略


当我们分表分库后,就不可以使用数据库的自增id了,否则肯定会出现id一样的数据。

因此就需要使用分布式ID生成策略进行id的生成。

mycat序列号(文件)

在mycat中提供了全局序列号:

sequence_conf.properties文件中:

# 表示使用过的历史分段(一般无特殊需要可不配置)
GLOBAL_SEQ.HISIDS=  
# 最小ID值
GLOBAL_SEQ.MINID=1001
# 最大ID值
GLOBAL_SEQ.MAXID=1000000000
# 当前ID值。
GLOBAL_SEQ.CURID=1000

同时在server.xml中,提供了配置生成id的方式:

 <system>
        ................
        <property name="sequenceHandlerType">2</property>
</system>

其中,该属性有4个取值:

<!--
    0:文件方式
    1:数据库方式
    2:时间戳方式
    3:zk
--/>

当为0时,采用文件的方式,在上面的sequence_conf.properties文件中,我们可以自定义策略,比如我们要操作order表,就可以以ORDER为前缀配置最大和最小id:

ORDER.HISIDS=
ORDER.MINID=1
ORDER.MAXID=200000
ORDER.CURID=12002

在使用插入的时候需要注意,id列的写法为next value for MYCATSEQ_前缀,如:

INSERT INTO t_order(order_id,content) values('next value for MYCATSEQ_ORDER','heihei')

该条数据的id就从12002开始,即12003:

在这里插入图片描述

缺点

当MyCAT重新发布后,配置文件中的sequence会恢复到初始值。

优点

本地加载,读取速度较快。

使用数据库的策略

在mycat的dbseq.sql文件中有如下建表和函数语句用于基于数据库生成id:

DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (  name VARCHAR(64) NOT NULL,  current_value BIGINT(20) NOT NULL,  increment INT NOT NULL DEFAULT 1, PRIMARY KEY (name) ) ENGINE=InnoDB;

-- ----------------------------
-- Function structure for `mycat_seq_currval`
-- ----------------------------
DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_currval`(seq_name VARCHAR(64)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    SET retval="-1,0";
    SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval FROM MYCAT_SEQUENCE  WHERE name = seq_name;
    RETURN retval ;
END
;;
DELIMITER ;

-- ----------------------------
-- Function structure for `mycat_seq_nextval`
-- ----------------------------
DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(64)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE val BIGINT;
    DECLARE inc INT;
    DECLARE seq_lock INT;
    set val = -1;
    set inc = 0;
    SET seq_lock = -1;
    SELECT GET_LOCK(seq_name, 15) into seq_lock;
    if seq_lock = 1 then
      SELECT current_value + increment, increment INTO val, inc FROM MYCAT_SEQUENCE WHERE name = seq_name for update;
      if val != -1 then
          UPDATE MYCAT_SEQUENCE SET current_value = val WHERE name = seq_name;
      end if;
      SELECT RELEASE_LOCK(seq_name) into seq_lock;
    end if;
    SELECT concat(CAST((val - inc + 1) as CHAR),",",CAST(inc as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;

-- ----------------------------
-- Function structure for `mycat_seq_setvals`
-- ----------------------------
DROP FUNCTION IF EXISTS `mycat_seq_nextvals`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_nextvals`(seq_name VARCHAR(64), count INT) RETURNS VARCHAR(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE val BIGINT;
    DECLARE seq_lock INT;
    SET val = -1;
    SET seq_lock = -1;
    SELECT GET_LOCK(seq_name, 15) into seq_lock;
    if seq_lock = 1 then
        SELECT current_value + count INTO val FROM MYCAT_SEQUENCE WHERE name = seq_name for update;
        IF val != -1 THEN
            UPDATE MYCAT_SEQUENCE SET current_value = val WHERE name = seq_name;
        END IF;
        SELECT RELEASE_LOCK(seq_name) into seq_lock;
    end if;
    SELECT CONCAT(CAST((val - count + 1) as CHAR), ",", CAST(val as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;

-- ----------------------------
-- Function structure for `mycat_seq_setval`
-- ----------------------------
DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_setval`(seq_name VARCHAR(64), value BIGINT) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE inc INT;
    SET inc = 0;
    SELECT increment INTO inc FROM MYCAT_SEQUENCE WHERE name = seq_name;
    UPDATE MYCAT_SEQUENCE SET current_value = value WHERE name = seq_name;
    SELECT concat(CAST(value as CHAR),",",CAST(inc as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;

INSERT INTO MYCAT_SEQUENCE VALUES ('GLOBAL', 1, 1);

MYCAT_SEQUENCE 的三个字段:

  • name sequence名称
  • current_value 当前value
  • increment 增长步长 可理解为mycat在数据库中一次读取多少个sequence. 当这些用完后, 下次再从数据库中读取.

插入一条数据,用于order表id生成:

INSERT INTO `mycatDB`.`MYCAT_SEQUENCE`(`name`, `current_value`, `increment`) VALUES ('ORDER', 20101, 100);

接着需要在sequence_db_conf.properties中进行配置:

ORDER=localdn

指定某个sequence哪个节点上,与dataNode的name对应。

别忘了将server.xml中该属性改为1

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

然后就可以测试了:

INSERT INTO t_order(order_id,content) values('next value for MYCATSEQ_ORDER','lala')

后缀和上面的表中的name名一致,

在这里插入图片描述

可以看到新的数据从20101后开始,插入完后,MYCAT_SEQUENCE表中ORDER的当前值变成了20201,因为会一次读取100个,用完后再读取下100个。

缺点

这种策略,只能在当前库中使用, 但是如果进行分库,那么在多个库中,就一定会出现id相同的问题。

时间戳策略

这个很简单,就会根据时间戳生成,将server.xml中那个属性的类型修改为2即可。

<property name="sequenceHandlerType">2</property>

sequence_time_conf.properties

    # 0-31为整数,每一个mycat节点的这两个配置值都不一样
    WORKID=01
    DATAACENTERID=01

插入:

在这里插入图片描述

Zookeper策略

将上面类型修改为3.

然后 mycat的myid.properties中配置ZK:

loadZK一定要开启

loadZk=true
zkURL=127.0.0.1:2181
clusterId=01
myid=mycat_01
clusterSize=1
clusterNodes=mycat_01

sequence_distributed_conf.properties

INSTANCEID=ZK
CLUSTERID=01

emmm用zookeper的方式的时候启动有点问题,暂时不知道是哪里的问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值