Chinaunix首页 | 论坛 | 博客
  • 博客访问: 549899
  • 博文数量: 36
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1749
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-20 16:13
个人简介

中国科学院大学计算机硕士,曾在新浪爱彩数据库组带DBA团队,现居新加坡。wx: lihui_dba

文章分类

全部博文(36)

文章存档

2020年(2)

2019年(3)

2017年(7)

2016年(1)

2015年(7)

2014年(11)

2013年(5)

分类: Mysql/postgreSQL

2017-10-11 19:31:13

前言:

使用MyCat的朋友应该有很大一部分是要做sharding的,而拆分面临的很大一个问题就是全局自增序列没有了。MyCat的开发人员早就考虑到了这一点,并提供了实现全局自增序列的方案,实现方式大概有“本地文件”、“数据库”、“本地时间戳”、“catlet注解”、“zookeeper”、“last_insert_id”这几种。每种方式可能都有自己的优缺点,要根据自己的实际情况选用。如果自己有第三方的全局序列方案更优,就不要用MyCat的方案了。MyCat中文档比较详细,并且实现起来比较靠谱的是数据库方式。下面的文档就只讨论数据库方式,基于MyCat1.6稳定版。

实现原理:

在数据库中创建一张table和几个function,记录需要自增值的表名、目前的自增值、步长,当需要新的自增值时,操作此表即可。

注意事项:

1.若某次读取的sequence没有用完系统就宕机了,则本地已经读取并且未使用的sequence会被丢弃。
2.改造之后,要检查线上环境insert into语句的兼容性,例如insert into table(id) values();这种可能就不被支持。

配置过程:

1.在server.xml中把生成全局序列的方式改为数据库方式
1
sequnceHandlerType配置为1,就是使用数据库方式生成sequence。

2.在一个指定的
数据库中创建指定的sequence表,并插入数据。

点击(此处)折叠或打开

  1. CREATE TABLE `MYCAT_SEQUENCE` (
  2.   `name` varchar(50) NOT NULL,
  3.   `current_value` int(11) NOT NULL,
  4.   `increment` int(11) NOT NULL DEFAULT '1',
  5.   PRIMARY KEY (`name`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

  7. insert into MYCAT_SEQUENCE(name,current_value,increment) values('DATETIME_TEST',1,1);
这个数据表的名字和列都不要改,后面的function会读写此表。自增步长increment这一列的默认值可以自己改。
数据库不需要和生产DB混在一起,独立出来最好,但是注意别放到异地,同一交换机(网段)内即可。否则并发获取自增值时性能无法保证。
创建时直接到后端的MySQL上创建,不要在MyCat中创建,因为schema.xml中如果没配置此表,创建会报错。

3.在同一台机器上创建相关的几个function

同上,直接在后端指定的MySQL上创建即可。数据库记得打开log_bin_trust_function_creators=1的选项。

点击(此处)折叠或打开

  1. #取当前squence的值
  2. DROP FUNCTION IF EXISTS mycat_seq_currval;
  3. DELIMITER $$
  4. CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50))RETURNS VARCHAR(64) CHARSET 'utf8'
  5. BEGIN
  6. DECLARE retval VARCHAR(64);
  7. SET retval='-999999999,NULL';
  8. SELECT CONCAT(CAST(current_value AS CHAR),',',CAST(increment AS CHAR)) INTO retval FROM
  9. MYCAT_SEQUENCE WHERE NAME = seq_name;
  10. RETURN retval;
  11. END$$
  12. DELIMITER ;

  13. #设置 sequence 值
  14. DROP FUNCTION IF EXISTS mycat_seq_setval;
  15. DELIMITER $$
  16. CREATE FUNCTION mycat_seq_setval(seq_name VARCHAR(50),VALUE INTEGER) RETURNS VARCHAR(64) CHARSET 'utf8'
  17. BEGIN
  18.    UPDATE MYCAT_SEQUENCE SET current_value = VALUE WHERE NAME = seq_name;
  19. RETURN mycat_seq_currval(seq_name);
  20. END$$
  21. DELIMITER ;

  22. #取下一个sequence的值
  23. DROP FUNCTION IF EXISTS mycat_seq_nextval;
  24. DELIMITER $$
  25. CREATE FUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS VARCHAR(64) CHARSET 'utf8'
  26. BEGIN
  27. UPDATE MYCAT_SEQUENCE SET current_value = current_value + increment
  28. WHERE NAME = seq_name;
  29. RETURN mycat_seq_currval(seq_name);
  30. END$$
  31. DELIMITER ;

4.配置
数据表(需要使用全局序列的)从哪里读取全局序列

点击(此处)折叠或打开

  1. root# vim conf/sequence_db_conf.properties
  2. 增加DATETIME_TEST=dn8
DATETIME_TEST即是我们需要使用全局序列的表,据说这个配置文件中表名一定要大写。
dn8即是在schema.xml中配置的datanode节点。这个节点就是刚刚我们创建MYCAT_SEQUENCE表的节点。

5.配置MYCAT_SEQUENCE表的datanode,和需要使用全局序列的表的自增属性

点击(此处)折叠或打开

  1. <schema name="xxx" checkSQLschema="false">
  2.                
  3.                
  4.                 <table name="datetime_test" primaryKey="id" autoIncrement="true" dataNode="dn3,dn4,dn5,dn6,dn7"
  5.                        rule="sharding-by-date" />

  6.         </schema>


  7.         <dataNode name="dn3" dataHost="master_server" database="db0" />
  8.         <dataNode name="dn4" dataHost="master_server" database="db1" />
  9.         <dataNode name="dn5" dataHost="master_server" database="db2" />
  10.         <dataNode name="dn6" dataHost="master_server" database="db3" />
  11.         <dataNode name="dn7" dataHost="master_server" database="db4" />
  12.        
  13.         <dataNode name="dn8" dataHost="sequence_server" database="sequence_db" />


  14.         <dataHost name="master_server" maxCon="1000" minCon="10" balance="0"
  15.                           writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
  16.                 <heartbeat>show slave status</heartbeat>
  17.                 <!-- can have multi write hosts -->
  18.                 <writeHost host="hostM1" url="vip:3306" user="xxx" password="xxx" />
  19.         </dataHost>

  20.         
  1.         <dataHost name="sequence_server" maxCon="1000" minCon="10" balance="0"
  2.                           writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
  3.                 <heartbeat>select user()</heartbeat>
  4.                 <!-- can have multi write hosts -->
  5.                 <writeHost host="hostM1" url="vip:3306" user="xxx" password="xxx" />
  6.         </dataHost>
6.使上述配置生效
MyCat中执行reload @@config;

7.进行测试

点击(此处)折叠或打开

  1. #在MyCat中插入一组数据,然后查看全局自增是否生效
  2. mysql> insert into datetime_test(create_time) values('2017-01-02 00:00:00'),('2017-01-03 00:00:00'),('2017-01-04 00:00:00'),('2017-01-05 00:00:00'),('2017-01-06 00:00:00'),('2017-01-07 00:00:00'),('2017-01-08 00:00:00'),('2017-01-09 00:00:00'),('2017-01-10 00:00:00');

  3. mysql> select * from datetime_test;
    +----+---------------------+
    | id | create_time         |
    +----+---------------------+
    |  2 | 2017-01-01 00:00:00 |
    |  3 | 2017-01-02 00:00:00 |
    |  6 | 2017-01-05 00:00:00 |
    | 11 | 2017-01-10 00:00:00 |
    |  7 | 2017-01-06 00:00:00 |
    |  5 | 2017-01-04 00:00:00 |
    | 10 | 2017-01-09 00:00:00 |
    |  8 | 2017-01-07 00:00:00 |
    |  4 | 2017-01-03 00:00:00 |
    |  9 | 2017-01-08 00:00:00 |
    +----+---------------------+
    10 rows in set (0.01 sec)

这个表的Sharding方式自己配置即可。

参考资料:

1.《分布式架构架构及企业实践--基于MyCat中间件》

阅读(1462) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~