您的位置:首页 > 产品设计 > UI/UE

Mycat全局Sequence详解

2015-09-20 14:41 495 查看

Mycat全局Sequence详解

在分布数数据库设计环节,将一个大表切分成各个子表,并且存储到各个数据节点上,如何保持一条数据记录的全局唯一性是一个关键性问题。mycat提供了一种全局sequence的机制,并且提供了多种实现方案。该文将对Mycat这一块进行讨论,以理清mycat这一块的设计思路。

mycat当前提供了master分支提供了三种全局sequence实现方式,还有一种zookeeper好像还处于开发阶段,没有看到完整的实现代码。下面将对这三种实现方式进行讨论。

从哪里配置采用那种全局Sequence实现

在SystemConfig中有如下几行代码:

<!--lang:java-->
public static final int SEQUENCEHANDLER_LOCALFILE = 0;
public static final int SEQUENCEHANDLER_MYSQLDB = 1;
public static final int SEQUENCEHANDLER_LOCAL_TIME = 2;
private int sequnceHandlerType = SEQUENCEHANDLER_LOCALFILE;

这里可以看到提供了三种实现方式。看到上面,如果熟悉mycat的话就应该知道在哪里配置
sequnceHandlerType
参数了。如果不熟悉也没关系,下面我告诉大家,在mycat的conf/server.xml的<system>标签内添加
<property name="sequnceHandlerType">1/0/2</property>
,在
<system>
标签内的所有
<property>
标签都会通过
name
属性找到
SystemConfig
中的属性并且自动将配置的值赋予到对应的属性中去(这部分实现可以看看
XMLServerLoader
loadSystem
实现)。

mycat对于sequence生成策略抽象出了一个接口-
SequenceHandler
,这个接口提供的实现类有
IncrSequenceMySQLHandler
,
IncrSequencePropHandler
,
IncrSequenceTimeHandler
IncrSequenceZKHandler
,其中
IncrSequenceZKHandler
还没有具体的实现。通过类名应该知道了具体哪个类实现了哪个sequence策略类型。比如
SEQUENCEHANDLER_LOCALFILE
策略是
IncrSequencePropHandler
实现类,
SEQUENCEHANDLER_MYSQLDB
策略是
IncrSequenceMySQLHandler
实现类,
SEQUENCEHANDLER_LOCAL_TIME
IncrSequenceTimeHandler
实现类。说到这里感觉mycat对于插件化这一块做的不够好,比如这里的sequence策略实现,完全可以插件化,但是从mycat加载各个具体实现的地方,都是通过硬编码去获取具体实现,而没有提供一种外部去接入的地方,所以如果外部需要实现自己的sequence策略,只能修改源码,这方面感觉还不够开放,例如下面硬编码获取具体实现:

<!--lang:java-->
public DruidSequenceHandler(int seqHandlerType) {
    switch(seqHandlerType){
    case SystemConfig.SEQUENCEHANDLER_MYSQLDB:
        sequenceHandler = IncrSequenceMySQLHandler.getInstance();
        break;
    case SystemConfig.SEQUENCEHANDLER_LOCALFILE:
        sequenceHandler = IncrSequencePropHandler.getInstance();
        break;
    case SystemConfig.SEQUENCEHANDLER_LOCAL_TIME:
        sequenceHandler = IncrSequenceTimeHandler.getInstance();
        break;
    default:
        throw new java.lang.IllegalArgumentException("Invalid sequnce handler type "+seqHandlerType);
    }
}

上面配置完值,如何在插入的时候从sequence获取值呢?这方面mycat提供了一种规范,通过“next value for MYCATSEQ_SEQUENCENAME”方式获取下一个sequence值。
比如
insert into t_users (id,province_code) values(next value for MYCATSEQ_USERS,"110000");
,t_user的id属性mycat会自动从全局USERS sequence中获取一个值。

上面列出了mycat在sequence策略方面的三个具体实现(其中zk还没有实现完,所以是三个),那么下面将对这三个实现进行介绍。

SEQUENCEHANDLER_LOCALFILE(0)

这种方式的实现是通过
IncrSequencePropHandler
类去实现,也是mycat提供默认的实现方式。通过静态配置文件来设置全局sequence的取值范围。各个全局sequence的配置放在sequence_conf.properties文件中,格式如下:

<!--lang:java-->
#default global sequence
GLOBAL.HISIDS= //GLOBAL sequence历史的分片区间
GLOBAL.MINID=10001  //GLOBAL sequence 当前获取的最小值
GLOBAL.MAXID=20000  //GLOBAL sequence 当前能够获取的最大id
GLOBAL.CURID=10000 //GLOBAL sequence 当前的值

其中
GLOBAL
就是sequence的名称,比如你创建一个USER的sequence,就如下进行创建:

<!--lang:java-->
#default user sequence
USER.HISIDS= //USER sequence历史的分片区间
USER.MINID=10001    //USER sequence 当前获取的最小值
USER.MAXID=20000    //USER sequence 当前能够获取的最大id
USER.CURID=10000 //USER sequence 当前的值

mycat每次从sequence_conf.properties获取一个sequence之后将会把CURID跟新到sequence_conf.properties文件中,并且如果当前的CURID大于MAXID,则会自动扩容,并且扩容的区间范围是和设置的范围一样。

SEQUENCEHANDLER_MYSQLDB(1)

这种方式是将sequence信息存储在数据库中,并且在对应数据库中执行响应的存储过程,然后mycat会调用对应的存储过程获取对赢的sequence,存储过程可以从这里获取。这部分在Mycat里面的具体实现是在
IncrSequenceMySQLHandler
中。在使用这个进行存储和获取sequence的时候,需要配置sequence的表是在哪个数据节点上,这些信息是配置在conf/sequence_db_conf.properties文件中。格式如下:

<!--lang:java-->
#sequence stored in datanode
GLOBAL=sequence //sequence名称=数据节点名称(配置在schema.xml里面)
USERS=sequence
ORDERS=sequence

SEQUENCEHANDLER_LOCAL_TIME(2)

这种方式有点类似采用UUID的方式来生成一个全局的唯一标识,这种规则的实现实在唉
IncrSequenceTimeHandler
中。需要配置conf/sequence_time_conf.properties文件。格式如下:
<!--lang:java-->

sequence depend on TIME

WORKID=01   
DATAACENTERID=01
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: