在实现分库分表的情况下,数据库自增主键已经无法保证在集群中是全局唯一的主键了,因此mycat提供了全局的sequence,并且提供了本地配置、数据库配置等多种实现方式。

本地文件方式

采用该方式,mycat将sequence配置到classpath目录的sequence_conf.properties文件中,在sequence_conf.properties文件做如下配置

GLOBAL_SEQ.HISIDS=
GLOBAL_SEQ.MINID=1001
GLOBAL_SEQ.MAXID=100000000
GLOBAL_SEQ.CURID=1000

其中HISIDS表示历史分段(一般无特殊需要则可以不配置),MINID表示最新的ID值,MAXID表示最大的ID值,CURID表示当前的ID值。
需要启用这种方式,则首先需要在servier.xml中配置如下参数:

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

注意:sequnceHandlerType配置为0,表示使用本地文件方式

采用这种方式的缺点是mycat重新发布后,配置文件中的sequence会恢复到初始值,有点事本地加载且读取速度快。

数据库方式

在数据库中创建一张表名为sequence的表,有sequence的当前值(current_value)、步长(increment int 类型,指每次读取多少个sequence,假设值为K)等信息。

squence的获取步骤如下:

1)每次使用sequence时候,根据传入的sequence名称,从数据库表中 读取current_value、increment到mycat中,并将数据库中的current_value 修改为current_value + increment的值。
2)mycat将读取到的current_value+increment 作为本次使用的sequence值,在下次使用的时候,sequence自动加1,当使用increment次后,执行与步骤一相同操作。
3)mycat负责维护这张表,用到哪些sequence时,主需要在这张表插入一条记录即可,若某次读取sequence没有用完就宕机了,则本次已经读取sequence且未使用的值将会被丢弃。

若要启用这种方式,需要在server.xml中配置如下参数:
<system><property name="sequnceHandlerType">1</property></system>

注意:这里配置成1,表示使用数据库方式生成sequence.

数据库配置如下:

创建MYCAT_SEQUENCE的表
CREATE DATABASE `mycat_mobp2p` DEFAULT CHARACTER SET utf8;

use mycat_mobp2p;

CREATE TABLE `MYCAT_SEQUENCE` (
`NAME` varchar(50) NOT NULL,
`current_value` int(11) NOT NULL,
`increment` int(11) NOT NULL DEFAULT '100',
PRIMARY KEY (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

name、current_value和increment 分别sequence的名称、当前value的值和增长步长。

插入一条sequence语句:
USER 是已经创建好的逻辑表,已经做好了相关rule

insert into MYCAT_SEQUENCE(name,current_value,increment) VALUES('USER',10000,100);

创建相关的function

DELIMITER $$
USE `mycat_mobp2p`$$
DROP FUNCTION IF EXISTS `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$$
DELIMITER ;

DELIMITER $$
USE `mycat_mobp2p`$$
DROP FUNCTION IF EXISTS `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$$
DELIMITER ;

DELIMITER $$
USE `mycat_mobp2p`$$
DROP FUNCTION IF EXISTS `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$$
DELIMITER ;

equence_db_conf.properties指定 sequence 相关配置在哪个节点上,配置如下:
[root@canal3 conf]# cat sequence_db_conf.properties
GLOBAL=dn1
COMPANY=dn1
CUSTOMER=dn1
ORDERS=dn1
USER=dn2

注意:USER必须为大写,这个与表的数据是否大写无关,事实上,MYCAT_SEQUENCE中name是否大小写对结果没有影响。

[root@canal3 conf]# cat schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="integration01" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" primaryKey="id" autoIncrement="true" subTables="user$1-10" rule="mod-long" dataNode="dn1"></table >
</schema>
<dataNode name="dn1" dataHost="integration01" database="integration01"/>
<dataNode name="dn2" dataHost="mycat_mobp2p" database="mycat_mobp2p"/>

<dataHost name="integration01" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>show slave status</heartbeat>
<writeHost host="10.40.20.44" url="10.40.20.44:3307" user="root" password="chengce243">
<readHost host="10.40.20.44" url="10.40.20.44:3308" user="root" password="chengce243"/>
</writeHost>
</dataHost>

<dataHost name="mycat_mobp2p" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="10.40.20.44" url="10.40.20.44:3307" user="root" password="chengce243">
</writeHost>
</dataHost>

</mycat:schema>

[root@canal3 conf]# cat server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License. - You
may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
- - Unless required by applicable law or agreed to in writing, software -
distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
License for the specific language governing permissions and - limitations
under the License. -->
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="nonePasswordLogin">0</property> <!-- 0为需要密码登陆、1为不需要密码登陆 ,默认为0,设置为1则需要指定默认账户-->
<property name="useHandshakeV10">1</property>
<property name="useSqlStat">0</property> <!-- 1为开启实时统计、0为关闭 -->
<property name="useGlobleTableCheck">0</property> <!-- 1为开启全加班一致性检测、0为关闭 -->

<property name="sequnceHandlerType">1</property>
<property name="subqueryRelationshipCheck">false</property> <!-- 子查询中存在关联查询的情况下,检查关联字段中是否有分片字段 .默认 false -->
<!-- <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议-->
<!-- <property name="fakeMySQLVersion">5.6.20</property>--> <!--设置模拟的MySQL版本号-->
<!-- <property name="processorBufferChunk">40960</property> -->
<!--
<property name="processors">1</property>
<property name="processorExecutor">32</property>
-->
<!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool -->
<property name="processorBufferPoolType">0</property>
<!--默认是65535 64K 用于sql解析时最大文本长度 -->
<!--<property name="maxStringLiteralLength">65535</property>-->
<!--<property name="sequnceHandlerType">0</property>-->
<!--<property name="backSocketNoDelay">1</property>-->
<!--<property name="frontSocketNoDelay">1</property>-->
<!--<property name="processorExecutor">16</property>-->
<!--
<property name="serverPort">8066</property> <property name="managerPort">9066</property>
<property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property>
<property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
<!--分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志-->
<property name="handleDistributedTransactions">0</property>

<!--
off heap for merge/order/group/limit 1开启 0关闭
-->
<property name="useOffHeapForMerge">1</property>

<!--
单位为m
-->
<property name="memoryPageSize">64k</property>

<!--
单位为k
-->
<property name="spillsFileBufferSize">1k</property>

<property name="useStreamOutput">0</property>

<!--
单位为m
-->
<property name="systemReserveMemorySize">384m</property>

<!--是否采用zookeeper协调切换 -->
<property name="useZKSwitch">false</property>

<!-- XA Recovery Log日志路径 -->
<!--<property name="XARecoveryLogBaseDir">./</property>-->

<!-- XA Recovery Log日志名称 -->
<!--<property name="XARecoveryLogBaseName">tmlog</property>-->

</system>

<!-- 全局SQL防火墙设置 -->
<!--白名单可以使用通配符%或着*-->
<!--例如<host host="127.0.0.*" user="root"/>-->
<!--例如<host host="127.0.*" user="root"/>-->
<!--例如<host host="127.*" user="root"/>-->
<!--例如<host host="1*7.*" user="root"/>-->
<!--这些配置情况下对于127.0.0.1都能以root账户登录-->
<!--
<firewall>
<whitehost>
<host host="1*7.0.0.*" user="root"/>
</whitehost>
<blacklist check="false">
</blacklist>
</firewall>
-->

<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">integration01</property>

<!-- 表级 DML 权限设置 -->
</user>

<user name="user">
<property name="password">user</property>
<property name="schemas">integration01</property>
<property name="readOnly">false</property>
</user>

</mycat:server>

使用示例:
insert into user (borrow_nid,create_user,create_time,update_time) values('201802051008888','dba',now(),now());
insert into user (borrow_nid,create_user,create_time,update_time) values('201802051007777','dba',now(),now());
insert into user (borrow_nid,create_user,create_time,update_time) values('201802051006666','dba',now(),now());
insert into user (borrow_nid,create_user,create_time,update_time) values('201802051005555','dba',now(),now());
insert into user (borrow_nid,create_user,create_time,update_time) values('201802051004444','dba',now(),now());

如果执行时报错:you might want to use the less safe log_bin_trust_function_creators variable。
解决办法:在 my.cnf中设置 SET GLOBAL log_bin_trust_function_creators = 1;

这样做虽然MyCat为无状态而且id有持久化,并且一次可以取出多个id,通过配置可以有主从切换。但是,id还是纯数字,没有有意义的信息,而且,MyCat主从切换并不可靠,id生成有故障,则整个服务都无法正常进行,这在架构上有单点问题,是不推荐的。

最新文章

  1. ajax和sap以及网络安全
  2. C# 的析构
  3. Windows Server 2008 系统设置集合
  4. unity3d 特殊文件夹和脚本编译顺序
  5. python_如何建立包
  6. 20145218 《Java程序设计》第01次实验报告
  7. python 基础——常用日志装饰器
  8. 全表扫描引发的db file sequential read
  9. 委托,匿名方法,Lambda,泛型委托,表达式树
  10. Ubuntu学习-简单指令
  11. grub4dos新手指南-2
  12. ant调用shell命令(Ubuntu)
  13. How to work with my desktop and laptop
  14. SQL 和 NoSQL 的区别
  15. 在java中如何处理日期格式问题
  16. SpringBoot整合Shiro使用Ehcache等缓存无效问题
  17. openssl passwd
  18. java入门学习(十四)运算语句for
  19. 如何理解IPD+CMMI+Scrum一体化研发管理解决方案之Scrum篇
  20. 关于已部署的WCF服务升级的问题

热门文章

  1. android图片特效处理之图片叠加
  2. thinkphp图片处理
  3. elasticsearch的master选举机制
  4. 1.17 Python基础知识 - 迭代器和生成器初识
  5. Vue的style与class
  6. method initializationerror not found:JUnit4单元測试报错问题
  7. Android 通过SOCKET下载文件的方法
  8. 【2017 Multi-University Training Contest - Team 10】Schedule
  9. QQ在线交谈代码
  10. jquery自动触发click事件