mycat insert into 全局表 selectinsert死锁 全局表 left join 分区表。目标全局表数据不一致,如何处理?

本文原文连接:
转载请注明出处!
1,迁移数据
举例说明,比如一个博客数据库数据表如下:
这里水平拆分,垂直拆分,只是做个简单的实验,真正的线上业务要根据情况,数据进行拆分。
CREATE TABLE category (
id INT NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL,
name VARCHAR(200) NOT NULL,
PRIMARY KEY (id)
CREATE TABLE tag (
id INT NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL,
name VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
CREATE TABLE `article` (
`id` int(11) NOT NULL PRIMARY KEY ,
`user_id` int(11) NOT NULL,
`title` varchar(200) NOT NULL,
`abstract` text,
`content` text,
`publish_time` datetime NOT NULL,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
`category_id` int(11) NOT NULL,
KEY `category_id` (`category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE article_tags (
user_id INT NOT NULL,
article_id INT NOT NULL,
tag_id INT NOT NULL,
PRIMARY KEY (user_id,article_id,tag_id)
CREATE TABLE user_info (
id INT NOT NULL AUTO_INCREMENT,
email VARCHAR(200) NOT NULL,
name VARCHAR(200) NOT NULL,
password VARCHAR(100) NOT NULL,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
last_login_time DATETIME NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY (name)
CREATE TABLE link (
id INT NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL,
name VARCHAR(100) NOT NULL,
url VARCHAR(300) NOT NULL,
PRIMARY KEY (id),
KEY (user_id)
将所有数据都迁移到mycat中,一共有4个数据库,blog01,blog02,blog_article01,blog_article02。
article,article_tags分别在blog_article01,blog_article02,按照uid进行水平拆分。
user_info表在blog01,link,category,tag在blog02数据库中。
CREATE DATABASE blog01 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_
CREATE DATABASE blog02 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_
CREATE DATABASE blog_article01 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_
CREATE DATABASE blog_article02 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_
#创建一共mycat数据库,存储mycat相关数据比如sequence。
CREATE DATABASE mycat DEFAULT CHARACTER SET utf8 COLLATE utf8_general_
2,schema.xml,配置
&?xml version="1.0"?&
&!DOCTYPE mycat:schema SYSTEM "schema.dtd"&
name="mycat" checkSQLschema="false" sqlMaxLimit="100"&
name="MYCAT_SEQUENCE" primaryKey="name" type="global" dataNode="nodeUser" /&
name="blog_user" checkSQLschema="false" sqlMaxLimit="100"&
name="user_info" primaryKey="id" type="global" dataNode="nodeUser" /&
name="blog_category" checkSQLschema="false" sqlMaxLimit="100"&
name="category" primaryKey="id" type="global" dataNode="nodeCategory" /&
name="tag" primaryKey="id" type="global" dataNode="nodeCategory" /&
name="link" primaryKey="id" type="global" dataNode="nodeCategory" /&
name="blog_article" checkSQLschema="false" sqlMaxLimit="100"&
name="article" primaryKey="user_id" dataNode="nodeArticle01,nodeArticle02" rule="mod-long" /&
name="article_tags" primaryKey="id" type="global" dataNode="nodeArticle01,nodeArticle02" /&
name="nodeMycat" dataHost="dataHost01" database="mycat" /&
name="nodeUser" dataHost="dataHost01" database="blog01" /&
name="nodeCategory" dataHost="dataHost01" database="blog02" /&
name="nodeArticle01" dataHost="dataHost01" database="blog_article01" /&
name="nodeArticle02" dataHost="dataHost01" database="blog_article02" /&
name="dataHost01" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native"&
&select 1&
host="hostM1" url="127.0.0.1:3306" user="root" password="root"/&
配置4个数据库连接,user_info做垂直拆分(配置type=global)。
blog_article,数据库进行水平拆分,拆分成两个数据库。
当设置成全局表的时候必须保证这个表在所有的数据库中,和配置的dataNode无关。
article规则配置:
&!DOCTYPE mycat:rule SYSTEM "rule.dtd"&
xmlns:mycat="http://org.opencloudb/"&
name="mod-long"&
&mod-long&
name="mod-long"
class="org.opencloudb.route.function.PartitionByMod"&
name="count"&2&
配置service.xml:
&?xml version="1.0" encoding="UTF-8"?&
&!DOCTYPE mycat:server SYSTEM "server.dtd"&
xmlns:mycat="http://org.opencloudb/"&
name="defaultSqlParser"&druidparser&
name="mycat"&
name="password"&mycat&
name="schemas"&mycat,blog_user,blog_category,blog_article&
3,数据库sequence生成
牵扯到分库的时候就一定要由sequence生成,mysql的主键自增就不能使用了。
mycat的文档里面没有找到这部分的配置资料,但是找到了sequence的存储过程。
可以把这个存储过程存储到一个单独的数据库中,然后进行一次查询,再做入库。
存储过程地址:
DROP TABLE IF EXISTS MYCAT_SEQUENCE;
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;
DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET latin1
DETERMINISTIC
DECLARE retval VARCHAR(64);
SET retval="-,null";
SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval
FROM MYCAT_SEQUENCE
WHERE name = seq_
DELIMITER ;
DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET latin1
DETERMINISTIC
UPDATE MYCAT_SEQUENCE
SET current_value = current_value + increment
WHERE name = seq_
RETURN mycat_seq_currval(seq_name);
DELIMITER ;
DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), value INTEGER) RETURNS varchar(64) CHARSET latin1
DETERMINISTIC
UPDATE MYCAT_SEQUENCE
SET current_value = value
WHERE name = seq_
RETURN mycat_seq_currval(seq_name);
DELIMITER ;
mysql& grant all privileges on *.* to root@"%" identified by ".";
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
4,测试mycat数据库
–mycat数据库的ip是192.168.1.16,端口是8066。
mysql -umycat -pmycat -P8066 -h 192.168.1.16
mysql& show
| DATABASE
| blog_article
| blog_category |
| blog_user
4 rows in set (0.00 sec)
mysql& use blog_
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql& show
| Tables in blog_user |
| user_info
1 row in set (0.00 sec)
mysql& insert into user_info(email,`name`,password,create_time,update_time,last_login_time) values('','zhangsan',password('123456'),now(),now(),now());
Query OK, 1 row affected (0.01 sec)
mysql& select * from user_
| id | email
| password
| create_time
| update_time
| last_login_time
| zhangsan | *6BB05EE4568DDA7DC67ED2CA2AD9 |
02:47:38 |
02:47:38 |
02:47:38 |
1 row in set (0.11 sec)
mysql& update user_info set name = 'lisi' where id = 1;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1
Changed: 1
Warnings: 0
mysql& delete from user_info where name = 'lisi';
Query OK, 1 row affected (0.00 sec)
mysql& use blog_
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql& show
| Tables in blog_category |
| category
3 rows in set (0.00 sec)
mysql& insert into tag(id,user_id,name) values(1,1,'java');
Query OK, 1 row affected (0.11 sec)
mysql& select * from
| id | user_id | name |
1 | java |
1 row in set (0.11 sec)
mysql& update tag set name = 'j2ee' where id = 1;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1
Changed: 1
Warnings: 0
mysql& insert into tag(user_id,name) values(2,'mysql');
Query OK, 1 row affected (0.00 sec)
mysql& select * from
| id | user_id | name
2 | mysql |
2 rows in set (0.00 sec)
mysql& delete from tag where id = 1;
Query OK, 1 row affected (0.00 sec)
mysql& use blog_
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
mysql& insert into article(id,user_id,title,publish_time,create_time,update_time,category_id) \
-& values (1,1,'test1',now(),now(),now(),1),(2,1,'test2',now(),now(),now(),2),\
-& (3,1,'test3',now(),now(),now(),3),(4,2,'test4',now(),now(),now(),3);
Query OK, 4 rows affected (0.00 sec)
Records: 3
Duplicates: 0
Warnings: 0
mysql& select * from
| id | user_id | title | abstract | content | publish_time
| create_time
| update_time
| category_id |
2 | test4 | NULL
03:30:55 |
03:30:55 |
03:30:55 |
1 | test1 | NULL
03:30:55 |
03:30:55 |
03:30:55 |
1 | test2 | NULL
03:30:55 |
03:30:55 |
03:30:55 |
1 | test3 | NULL
03:30:55 |
03:30:55 |
03:30:55 |
4 rows in set (0.00 sec)
mysql& update article set title = 'new title' where user_id = 1 and id =2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1
Changed: 1
Warnings: 0
测试sequence生成:
mysql& INSERT INTO MYCAT_SEQUENCE VALUES ('article_seq', 1, 1);
1 row in set (0.06 sec)
mysql& SELECT MYCAT_SEQ_CURRVAL('article_seq');
| MYCAT_SEQ_CURRVAL('article_seq') |
1 row in set (0.01 sec)
mysql& SELECT MYCAT_SEQ_SETVAL('article_seq', 2);
| MYCAT_SEQ_SETVAL('article_seq', 2) |
1 row in set (0.01 sec)
mysql& SELECT MYCAT_SEQ_CURRVAL('article_seq');
| MYCAT_SEQ_CURRVAL('article_seq') |
1 row in set (0.01 sec)
mysql& SELECT MYCAT_SEQ_NEXTVAL('article_seq');
| MYCAT_SEQ_NEXTVAL('article_seq') |
1 row in set (0.01 sec)
mysql& SELECT MYCAT_SEQ_NEXTVAL('article_seq');
| MYCAT_SEQ_NEXTVAL('article_seq') |
1 row in set (0.02 sec)
mycat提供了数据库垂直拆分和水平拆分的方案,对于数据迁移可以按照id,user_id进行拆分。
也可以将数据分库存储,不拆分,但必须放到不同的库中(和水平拆分的分开)。
同时,如果进行拆分,则需要修改主键生成方式,目前看到mycat中提供一个sequence的存储过程,可以直接使用。
Mycat(5):聊天消息表数据库按月分表实践,平滑扩展
业务需求比如一个社交软件,比如像腾讯的qq。可以进行群聊天(gid),也可以单人聊天。
数据量按月增加需要按月进行数据库拆分。
比如按照2015年进行12个月拆分,同时可以配合gid进行水平拆分...
Mycat单库分表实践
本文主要讲述Mycat单库分表的步骤,偏实践,不多讲理论。
我们知道数据拆分,有水平拆分和垂直拆分,具体的理论就不在这里赘述了。
Mycat采用的水平拆分,...
mycat中全局表的实战应用简析(上)
name表名称;
primaryKey为该表的主键type=”global” 是啥?
有几个特性:
1、和具体物理表一一对应
2、多节点配置时出现 新增、修改操作时,则mycat会对所有节点(...
Mycat(4):消息表mysql数据库分表实践
1,业务需求比如一个社交软件,比如像腾讯的qq。可以进行群聊天(gid),也可以单人聊天。
这里面使用到了数据库中间件mycat,和mysql数据表分区。
关于mycat分区参考:
【 数据库垂...
Mycat之——读写分离+垂直切分+水平切分+er分片+全局表 测试
今天,给大家带来一篇基于Mycat的读写分离+垂直切分+水平切分+er分片+全局表 测试 ,我们直接进入主题
读写分离:利用最基础的mysql主从复制,事务性的查询无法分离出去(因为会导致数据不一致...
思考如何设计或优化千万级别的大表?此外无其他信息,个人觉得这个话题有点范,就只好简单说下该如何做,对于一个存储设计,必须考虑业务特点,收集的信息如下:1.数据的容量:1-3年内会大概多少条数据,每条数...
表分割有两种方式:  
  1水平分割:根据一列或多列数据的值把数据行放到两个独立的表中。
  水平分割通常在下面的情况下使用。
  o表很大,分割后可以降低在查询时需要读的数据和索引的页数,同时也降...
垂直划分按照功能划分,把数据分别放到不同的数据库和服务器。当一个网站开始刚刚创建时,可能只是考虑一天只有几十或者几百个人访问,数据库可能就个db,所有表都放一起,一台普通的服务器可能就够了,而且开发人...
项目开发中,我们的数据库数据越来越大,随之而来的是单个表中数据太多。以至于查询书读变慢,而且由于表的锁机制导致应用操作也搜到严重影响,出现了数据库性能瓶颈。
当出现这种情况时,我们可以考虑分表,...
一、MySQL有一个MERGE存储引擎是专门做这个事情的,借这篇博文了解:Mysql MERGE引擎分表
三、select A.*,B.*,C.* from a...
没有更多推荐了,404 Not Found
The requested URL /q/0530 was not found on this server.数据库路由中间件MyCat - 使用篇(1)基本概念直接介绍概念太枯燥了,还是拿个和背景篇相似的例子介绍
业务场景:客户完成下单,快递员接受并更新运单状态,客户可以随时查看运单状态的任务。一票快递可能有多个子母件。同时,我们需要标记每个运单的状态,运单状态的解释和含义保存在运单状态字典表中。
因此,我们需要建立如下表:
我们现在按照业务将数据库垂直拆分成运单库(单表2000tps,6000W数据),快递员库(单表1500tps,100W数据),客户库(单表1500tps,1000W数据记录);假设每个MySQL数据库单表不能超过2000W数据,单表不能超过1000tps。那么运单库则需要分成3片,客户库需要分成2片,统一由MyCat管理。如下图所示: 1.逻辑库MyCat作为一个中间件,对应用应为无感知的。
应用访问MyCat,根据之前所述,应用感知到后台只是一个(或者多个,和访问MySQL实例一样)数据库(假设只有一个数据库,这个库叫SF,里面有运单相关表,快递员相关表和客户相关表);这里MyCat的数据库就是逻辑库。访问MyCat,结果应该如下面所示
虽然其中的表可能存在于不同的库,但是表面上,他们属于同一个MyCat实例中的同一个逻辑库。所以,虽然上面的架构图显示他们不在同一个数据库,但是在MyCat中,他们在同一个逻辑库。2.逻辑表在逻辑库下的表就是逻辑表。逻辑表可以分片,也可以不分片。 orders表明显是要分片的表,但是在MyCat看来,他们虽然分布在不同的分片节点上(分布在不同的MySQL数据库上),但仍视为是同一个逻辑表,在同一个逻辑库里。2.1分片表分片表,是指那些原有的很大数据的表,需要切分到多个数据库的表,这样,每个分片都有一部分数据,所有分片构成了完整的数据。分片表都有自己的分片规则,根据分片规则确定分片。
配置里面,如下配置:&table name="orders" primaryKey="id" dataNode="test$1-2" rule="mod-long"&
&/table&12意思就是用mod-long规则根据主键id将运单表orders分割到test1,test2这两个数据库(分片节点)上。 请求情况1:select * from orders where id = 1;1对于分片表的查询,如果按照分片列查询,则请求只会被发送到一个分片上。 请求情况2:select * from orders where id & 100 and id & 0;1对于分片表的查询,如果按照分片列范围(在字段类型支持范围的情况下)查询,则请求会根据分片规则计算两个边界值,然后将请求发送到对应结果的分片上,并合并每个分片的结果。 请求情况3:select * from orders where initialpoint = 'Beijing';1像这种根据非分片列查询的情况,请求会被发送到所有分片上,并合并每个分片的结果。 请求情况4:
请求为更新类型的sql语句,与查询的三种情况相同处理。2.2 非分片表一个数据库中并不是所有的表都很大,某些表是可以不用进行切分的,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。
例如:&table name="courier" primaryKey="id" dataNode="test3"&
&/table&12意思就是快递员表不用分片,保存在test3这个分片节点上。
对于非分片表的操作和对普通数据库的一样,因为不涉及到分布式数据库。2.3 ER表关系型数据库是基于实体关系模型(Entity-Relationship Model)之上,通过其描述了真实世界中事物与关系,Mycat中的ER表即是来源于此。根据这一思路,提出了基于E-R关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上,即子表依赖于父表,通过表分组(Table Group)保证数据Join不会跨库操作。
表分组(Table Group)是解决跨分片数据join的一种很好的思路,也是数据切分规划的重要一条规则。
name="orders" primaryKey="id" dataNode="test$1-2" rule="mod-long"&
name="orders_cargo" joinKey="order_id" parentKey="id"&
&123456运单表为分片表,运单表和运单子母件表为一对多关系,可以做成父子表。
对于子表的sql请求,都是通过joinKey对应到父表对应字段后,按照之前分片表的规则进行处理。2.4 全局表一个真实的业务系统中,往往存在大量的类似字典表的表,这些表基本上很少变动,字典表具有以下几个特性:变动不频繁数据量总体变化不大数据规模不大,很少有超过数十万条记录。对于这类的表,在分片的情况下,当业务表因为规模而进行分片以后,业务表与这些附属的字典表之间的关联,就成了比较棘手的问题,所以Mycat中通过数据冗余来解决这类表的join,即所有的分片都有一份数据的拷贝,所有将字典表或者符合字典表特性的一些表定义为全局表。
数据冗余是解决跨分片数据join的一种很好的思路,也是数据切分规划的另外一条重要规则
name="order_status_interception" primaryKey="id" type="global" dataNode="test$1-2"&
&123运单状态信息字典表,只是注释每种运单状态,就是典型的字典表,与分片表orders为多对一的关系。
对于全局表,所有的查询请求,只会发送到其中一个全局表分片上执行,所有的更新请求,会在每个全局表分片上执行。2.5 如何决定?根据之前的描述,我们可以推断出,对于分片表的修改和查询,如果是按照分片字段进行查找的话,则请求会被转发到一个分片上。如果不是按照分片字段的话,就会把请求发到每一个分片上进行查找。所以,分片字段的选择比较重要!对于全局表,相当于在每个分片上有一份相同的复制,修改请求会在每一个分片上执行,但是查询只会落到一个分片上。所以,全局表尽量是不会改变的而且是需要和分片表做Join操作的,如果经常改变或者不需要做join,最好还是做成非分片表。先抛出了这几种逻辑表的概念,大家先有个印象。现在我们结合具体实际讨论如何决定表的类型。 像这种简单的从属关系一对n的表,我们处理起来很简单,一般将它们按照需要做join的键设为父子表即可。但是下面的场景很麻烦,比如快递员与运单就是多对多的关系,客户对于运单也是多对多的关系(一个收方,一个寄方)。我们既有快递员需要查看自己的所有运单的场景和客户查看自己所有运单的场景。相对的,我们也有查看一个运单涉及到的快递员还有客户的场景。 customer表(客户表)以及courier表(快递员表)因为与分片表orders之间不做join操作,所以不用作为公共表。
首先,关系表可以作为公共表,这样的话,涉及到与分片表的join操作没有限制,因为在每个分片,公共表都是完整的。但是,关系表的更新很频繁,我们可能不能忍受每更新一次关系表就跑到每个分片上都更新一次(性能,可靠性考虑)。
那么作为运单的子表呢?那么查找一个运单涉及到的快递员还有客户就比较简单。因为根据运单号(也就是分片id)查询,MyCat就会根据分片规则给他定位到具体分片,而不是去按分片搜索。
但是相应的,快递员查看自己所有运单的场景就比较慢,因为请求是发送到每一个分片上查找。
作为快递员的子表也有同样的缺陷。
还有一种方法,就是这种关系表同时作为运单和快递员的子表。但是这样,目前需要应用自己去做双写。MyCat目前还没实现这种。当然,我觉得这是一个我们自己可以根据需要改进的地方。MyCat中间件根据关系冗余表关系进行双写另外,究竟取哪种方法,都是从业务出发去考虑的。在这里,如果从快递员出发去查找以及从运单出发去查找的业务压力差不多大的话,那么最好就采用关系表同时作为运单和客户的子表这种方法。然后将快递员和运单的业务独立,每个业务应用都去维护自己的关系表,同时通过消息队列来保持关系表之间的一致性。这样也不失为一种方法。首先,orders表可定是分片表。orders_cargo表是子母件表,一个order可能有多个子母件,所以,最好把orders_cargo作为orders的子表。
这种情况下,orders与orders_cargo按照对应键(就是子表按照哪个键与主表的哪个键对应进行分片。比如orders_cargo就是order_id与orders的id对应。这是以order_id与orders的id进行join结果就是对的)join结果也是正确的。
MyCat - 源代码篇(2)
数据库路由中间件MyCat - 源代码篇(2)2. 前端通信模块Created with Rapha?l 2.1.0MySql连接建立以及认证过程clientclientMySqlMySql1.TCP...
MyCat - 使用篇(2)
数据库路由中间件MyCat - 使用篇(2)基本概念3. 分片3.1 分片节点(dataNode)表被水平切分后,每个分片表所在的数据库就是一个分片节点。一个分片节点对应一个数据库(mysql数据库)...
MyCat - 使用篇(4)
数据库路由中间件MyCat - 使用篇(4)配置MyCat3. 配置conf/rule.xml1.4.1中的规则配置比较笨,1.5中优化了一些,将tableRule标签和function标签合并了,并...
MyCat - 源代码篇(5)
数据库路由中间件MyCat - 源代码篇(5)3. 连接模块如之前所述,MyCat的连接分为前端和后端,下面是连接基本相关类图:
3.1 ClosableConnection:public inte...
MYCAT使用篇(1)
安装mycatmycat下载,windows
http://dl.mycat.io/1.6-RELEASE/ 下载后解压JDK检查安装检查java的环境变量是否是1.7以上,如果不是安装1.7以上的...
MyCat - 源代码篇(16)
数据库路由中间件MyCat - 源代码篇(16)5. 路由模块5.5 AST语义解析路由DruidParser结构:
基本使用解析代码://sql是一组SQL语句
MySqlStatementPar...
Mycat源码篇 : MyCat线程模型分析
参考MyCat权威指南,对MyCat-Server里面的线程模型做简要分析
MyCat - 源代码篇(8)
数据库路由中间件MyCat - 源代码篇(8)3. 连接模块3.5 后端连接对于后端连接,我们只关心MySQL的。
从后端连接工厂开始MySQLConnectionFactory.java:
没有更多推荐了,mycat分片表全局自增主键测试
时间: 12:06:51
&&&& 阅读:363
&&&& 评论:
&&&& 收藏:0
标签:mycat分片表全局自增主键测试mycat分片表全局自增主键测试一、全局序列号介绍在实现分库分表的情况下,数据库自增主键已无法保证自增主键的全局唯一。为此,MyCat&提供了全局
sequence,并且提供了包含本地配置和数据库配置等多种实现方式。1.本地文件方式使用服务器本地磁盘文件的方式2.数据库方式使用专用数据库的方式3.本地时间戳方式使用时间戳算法方式4.分布式ZK ID 生成器基于ZK&与本地配置的分布式ID&生成器(可以通过ZK&获取集群(机房)唯一InstanceID,也可以通过配置文
件配置InstanceID)5.Zk 递增方式另一种ZK生成方式6.其他方式二、配置方式详解1.本地文件方式配置方式:在sequence_conf.properties 文件中做如下配置:#&这是全局表的设置
GLOBAL_SEQ.HISIDS=
GLOBAL_SEQ.MINID=1001
GLOBAL_SEQ.MAXID=
GLOBAL_SEQ.CURID=1000
#&下面是自定义表的设置其中HISIDS 表示使用过的历史分段(一般无特殊需要可不配置),MINID 表示最小ID 值,MAXID 表示最大ID 值,CURID 表示当前ID 值。server.xml 中配置:&system&&property&name="sequnceHandlerType"&0&/property&&/system&注:sequnceHandlerType 需要配置为0,表示使用本地文件方式。使用示例:insert&into&table1(id,name)&values(next&value&for&MYCATSEQ_GLOBAL,‘test’);缺点:当MyCAT 重新发布后,配置文件中的sequence 会恢复到初始值。优点:本地加载,读取速度较快。[本地文件方式详细配置和测试]1.1 修改配置文件server.xml,指定加密方式为本地文件方式&system&&property&name="sequnceHandlerType"&0&/property&&/system&1.2 在schema.xml文件中配置,增加表tt,ID为主键,在dn$1-3上分片,分片方式mod-log&table&name="tt"&primaryKey="id"&autoIncrement="true"&dataNode="dn$1-3"&rule="mod-long"/&1.3 修改sequence_conf.properties 文件中做如下配置:#&这是全局表的设置
GLOBAL.HISIDS=
GLOBAL.MINID=10001
GLOBAL.MAXID=
GLOBAL.CURID=10000
#&下面是自定义表的设置
TT.HISIDS=
TT.MINID=1001
TT.MAXID=2000
TT.CURID=10001.4 建表ttCREATE&TABLE&tt(
`id`&INT(10)&UNSIGNED&NOT&NULL&AUTO_INCREMENT,
`name_`&INT(10)&UNSIGNED&NOT&NULL,
PRIMARY&KEY&(`id`)
)&DEFAULT&CHARSET=utf8;查看表结构mysql&&desc&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+-------+------------------+------+-----+---------+----------------+
|&Field&|&Type&&&&&&&&&&&&&|&Null&|&Key&|&Default&|&Extra&&&&&&&&&&|
+-------+------------------+------+-----+---------+----------------+
|&id&&&&|&int(10)&unsigned&|&NO&&&|&PRI&|&NULL&&&&|&auto_increment&|
|&name_&|&int(10)&unsigned&|&NO&&&|&&&&&|&NULL&&&&|&&&&&&&&&&&&&&&&|
+-------+------------------+------+-----+---------+----------------+
2&rows&in&set&(0.01&sec)查看表分片情况mysql&&explain&select&*&from&
+-----------+--------------------------------+
|&DATA_NODE&|&SQL&&&&&&&&&&&&&&&&&&&&&&&&&&&&|
+-----------+--------------------------------+
|&dn1&&&&&&&|&SELECT&*&FROM&tt&LIMIT&3000000&|
|&dn2&&&&&&&|&SELECT&*&FROM&tt&LIMIT&3000000&|
|&dn3&&&&&&&|&SELECT&*&FROM&tt&LIMIT&3000000&|
+-----------+--------------------------------+
3&rows&in&set&(0.07&sec)1.5 插入数据测试插入一条使用全局序列号insert&into&tt(id,name_)&values(next&value&for&MYCATSEQ_GLOBAL,1);查看序列号使用mysql&&SELECT&*&FROM&TT;
+-------+-------+
|&id&&&&|&name_&|
+-------+-------+
|&10001&|&&&&&1&|
+-------+-------+
1&row&in&set&(0.00&sec)插入一条使用TT序列号insert&into&tt(id,name_)&values(next&value&for&MYCATSEQ_TT,2);查看序列好使用情况mysql&&SELECT&*&FROM&TT&ORDER&BY&name_;
+-------+-------+
|&id&&&&|&name_&|
+-------+-------+
|&10001&|&&&&&1&|
|&&1001&|&&&&&2&|
+-------+-------+
2&rows&in&set&(0.01&sec)多插入一些数据,查询结果mysql&&SELECT&*&FROM&TT&ORDER&BY&name_;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+-------+-------+
|&id&&&&|&name_&|
+-------+-------+
|&10001&|&&&&&1&|
|&&1001&|&&&&&2&|
|&&1002&|&&&&&3&|
|&&1003&|&&&&&4&|
|&&1004&|&&&&&5&|
|&&1005&|&&&&&6&|
+-------+-------+
6&rows&in&set&(0.00&sec)这些数据再分片上的情况mysql&(db1)&select&*&from&
+------+-------+
|&id&&&|&name_&|
+------+-------+
|&1002&|&&&&&3&|
|&1005&|&&&&&6&|
+------+-------+
2&rows&in&set&(0.00&sec)
mysql&(db2)&select&*&from&
+------+-------+
|&id&&&|&name_&|
+------+-------+
|&1003&|&&&&&4&|
+------+-------+
1&row&in&set&(0.00&sec)
mysql&(db3)&select&*&from&
+-------+-------+
|&id&&&&|&name_&|
+-------+-------+
|&&1001&|&&&&&2&|
|&&1004&|&&&&&5&|
|&10001&|&&&&&1&|
+-------+-------+OK It works!!优点:配置简单,本地文件,读写速度快
缺点:导致MYCAT变成有状态的中间件,不利于部署集群2.数据库方式数据库方式存在比较明显的缺点,即MYCAT集群切换和保持序列的数据库主从切换之后,不可控内容较多
需要非常仔细的处理这些问题,维护成本较高,虽然实现MYCAT无状态,但有单点问题3.本地时间戳方式ID= 64 位二进制 (42(毫秒)+5(机器 ID)+5(业务编码)+12(重复累加) server.xml:&system&&property&name="sequnceHandlerType"&2&/property&&/system&sequence_time_conf.properties:WORKID=0-31&任意整数
DATAACENTERID=0-31&任意整数是个好方式4.分布式ZK ID 生成器-----最想测试的还是这个配置选项:&property&name="sequnceHandlerType"&3&/property&原理说明:Zk 的连接信息统一在myid.properties 的zkURL 属性中配置。基于ZK 与本地配置的分布式ID 生成器(可以通过ZK 获取集群(机房)唯一InstanceID,也可以通过配置文件配置InstanceID)ID 结构:long 64 位,ID 最大可占63 位current time millis(微秒时间戳38 位,可以使用17 年)instanceId(实例ID,可以通过ZK 或者配置文件获取,5 位,也就是十进制0-31)threadId(线程ID,9 位)increment(自增,6 位)一共63 位,可以承受单机房单机器单线程)=640000 的并发。无悲观锁,无强竞争,吞吐量更高配置文件:sequence_distributed_conf.properties,只要配置里面:INSTANCEID=ZK 就是从ZK 上获取InstanceID。配置ZK ID生成器的主要步骤4.1 配置zookeeperzookeeper是hadoop的一个子项目一般生产上需要配置zookeeper集群,奇数个节点,至少三个节点为了测试mycat的相关特性,我们只搭建一个单节点的zookeeperZooKeeper Standalone模式从Apache网站上(zookeeper.apache.org)下载ZooKeeper软件包,我选择了3.3.4版本的(zookeeper-3.3.4.tar.gz),在一台Linux机器上安装非常容易,只需要解压缩后,简单配置一下即可以启动ZooKeeper服务器进程。将zookeeper-3.3.4/conf目录下面的 zoo_sample.cfg修改为zoo.cfg,配置文件内容如下所示:tickTime=2000
dataDir=/home/hadoop/storage/zookeeper
clientPort=2181
initLimit=5
syncLimit=2下面启动ZooKeeper服务器进程:cd&zookeeper-3.3.4/
bin/zkServer.sh&start这样zookeeper就可以使用了,防火墙的配置自行处理ZooKeeper 分布式模式搭建生产网络或夸机房分布式的时候再进行补充4.2 配置mycat主要涉及三个方面,修改myid.properties,修改server.xml,修改sequence_distributed_conf.propertiesmyid.properties:loadZk=true&&&&&&&&&&&&&&&&&#使用zk管理mycat和ID
zkURL=127.0.0.1:2181&&&&&&&&#zk服务器的地址和端口
clusterId=010&&&&&&&&&&&&&&&#本机房mycat集群的ID
myid=01001&&&&&&&&&&&&&&&&&&#集群内mycat的ID
clusterNodes=mycat-02&&&&&&&#mycat节点的名称
#server&&booster&&;&&&booster&install&on&db&same&server,will&reset&all&minCon&to&1
#type=server
#boosterDataHosts=dn2,dn3server.xml:&!DOCTYPE&mycat:server&SYSTEM&"server.dtd"&
&mycat:server&xmlns:mycat="http://io.mycat/"&
&&&&&system&
&&&&&&&&&property&name="defaultSqlParser"&druidparser&/property&
&&&&&&&&&property&name="useCompression"&1&/property&
&&&&&&&&&property&name="serverPort"&3306&/property&
&&&&&&&&&property&name="managerPort"&3308&/property&
&&&&&&&&&property&name="maxStringLiteralLength"&65535&/property&
&&&&&&&&&!--&sequnceHandlerType&0:文件模式&1:&2:3:zookeeper分布式管理模式&--&
&&&&&&&&&property&name="sequnceHandlerType"&3&/property&
&&&&&/system&
&&&&&user&name="root"&
&&&&&&&&&property&name="password"&password&/property&
&&&&&&&&&property&name="schemas"&dbykt&/property&
&&&&&/user&
&/mycat:server&sequence_distributed_conf.properties:INSTANCEID=01
CLUSTERID=01上面三个文件修改完成后,复制conf下的所有文件到 conf/zkconf/目录下cp&*.txt&*.xml&*.properties&zkconf/初始化:cd&./bin/
./init_zk_data.sh4.3 启动mycat先使用console看看启动是否正常./bin/mycat&console正常之后再进行启动./bin/mycat&start4.4 测试mycat ZK 分布式ID生成器使用工具Jmeter,此处不赘述配置表ot1:.....
&table&name="ot1"&dataNode="dn$1-20,dn$21-40,dn$41-60"&rule="card_no"&primaryKey="id"&autoIncrement="true"/&
......重启mycat./bin/mycat&restart建表(因为同时测试了插入性能,所以表较为复杂)CREATE&TABLE&`ot1`&(
&&`id`&bigint(20)&NOT&NULL&AUTO_INCREMENT,
...............
...............
&&PRIMARY&KEY&(`id`)
)&ENGINE=InnoDB&DEFAULT&CHARSET=utf8;Jmeter 插入数据测试使用的sql语句如下:INSERT&INTO&`ot1`&(
................
................
&&&&&&&&next&value&for&MYCATSEQ_OT,
...............
...............
&&&&);查询观察结果mysql&&SELECT&id&FROM&ot1&ORDER&BY&
|&6705980&|
|&6705981&|
|&0260414&|
|&3814784&|
|&3814847&|
|&9359105&|
|&6230018&|
|&6230019&|
|&6230020&|
|&6230021&|
|&9784454&|
|&9784455&|
|&9784456&|
|&3338889&|
|&3338890&|
|&6893323&|
|&6893324&|
|&0447757&|
|&0447758&|
|&4002191&|
........查询数据总量:mysql&&select&count(id)&id_count&from&ot1;
+----------+
|&id_count&|
+----------+
+----------+查出最大ID:mysql&&select&max(id)&id&from&ot1&;
+---------------------+
|&id&&&&&&&&&&&&&&&&&&|
+---------------------+
|&7897525&|
+---------------------+
1&row&in&set&(0.03&sec)判断一下是否有重复ID:mysql&&select&count(id),id&from&ot1&group&by&id&having&count(id)&1;
Empty&set&(1&min&42.85&sec)4.5 结论分布式ZK ID生成器,果然强大。这为数据库跨机房双活提供了新的方案,使得双A机房架构下的数据最终一致性有了新的思路。本文出自 “” 博客,请务必保留此出处标签:原文地址:http://mynode.blog.51cto.com/0570
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!

我要回帖

更多关于 hive分区表insert数据 的文章

 

随机推荐