mycat实现mysql读写分离实践
来自: http://my.oschina.net/rock912/blog/610878
mycat是一个的数据库中间件,基于阿里开源的cobar产品而研发,由几个有志之士的牛人共同完成并开源。提供高可用性数据分片集群,自动故障切换,高可用性 ,支持读写分离,支持Mysql双主多从,以及一主多从的模式 ,支持全局表,数据自动分片到多个节点,用于高效表关联查询 ,支持独有的基于E-R 关系的分片策略,实现了高效的表关联查询多平台支持,部署和实施简单。
今天来实践下用mycat实现mysql的读写分离,1.配置mysql端主从数据同步,2.用mycat实现读写分离,配置mysql端主从数据同步不作讲解,这里详细介绍下用mycat实现数据读写分离
新建数据库读库和写库
分别在两个不同主机下新建两个大库,读库r和写库w,在读库r下新建3个数据库分片(db1,db2,db3),在写库w下也新建3个分片(db1,db2,db3)。
1.db1分片脚本
/* Navicat MySQL Data Transfer Source Server : mysql Source Server Version : 50527 Source Host : localhost:3306 Source Database : db1 Target Server Type : MYSQL Target Server Version : 50527 File Encoding : 65001 Date: 2016-01-27 15:48:40 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `company` -- ---------------------------- DROP TABLE IF EXISTS `company`; CREATE TABLE `company` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of company -- ---------------------------- -- ---------------------------- -- Table structure for `customer` -- ---------------------------- DROP TABLE IF EXISTS `customer`; CREATE TABLE `customer` ( `ID` bigint(20) NOT NULL DEFAULT '0', `sharding_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of customer -- ---------------------------- INSERT INTO `customer` VALUES ('1', null); INSERT INTO `customer` VALUES ('4', '10000'); -- ---------------------------- -- Table structure for `employee` -- ---------------------------- DROP TABLE IF EXISTS `employee`; CREATE TABLE `employee` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of employee -- ---------------------------- -- ---------------------------- -- Table structure for `goods` -- ---------------------------- DROP TABLE IF EXISTS `goods`; CREATE TABLE `goods` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of goods -- ---------------------------- INSERT INTO `goods` VALUES ('11'); -- ---------------------------- -- Table structure for `hotnews` -- ---------------------------- DROP TABLE IF EXISTS `hotnews`; CREATE TABLE `hotnews` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of hotnews -- ---------------------------- -- ---------------------------- -- Table structure for `mycat_sequence` -- ---------------------------- DROP TABLE IF EXISTS `mycat_sequence`; 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; -- ---------------------------- -- Records of mycat_sequence -- ---------------------------- INSERT INTO `mycat_sequence` VALUES ('GLOBAL', '100400', '100'); -- ---------------------------- -- Table structure for `orders` -- ---------------------------- DROP TABLE IF EXISTS `orders`; CREATE TABLE `orders` ( `ID` bigint(20) NOT NULL DEFAULT '0', `customer_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of orders -- ---------------------------- INSERT INTO `orders` VALUES ('1', '1'); INSERT INTO `orders` VALUES ('4', '4'); -- ---------------------------- -- Table structure for `travelrecord` -- ---------------------------- DROP TABLE IF EXISTS `travelrecord`; CREATE TABLE `travelrecord` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of travelrecord -- ---------------------------- INSERT INTO `travelrecord` VALUES ('1'); INSERT INTO `travelrecord` VALUES ('4'); INSERT INTO `travelrecord` VALUES ('10001'); INSERT INTO `travelrecord` VALUES ('100400'); -- ---------------------------- -- Function structure for `mycat_seq_currval` -- ---------------------------- DROP FUNCTION IF EXISTS `mycat_seq_currval`; DELIMITER ;; CREATE DEFINER=`root`@`%` 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 ; -- ---------------------------- -- Function structure for `mycat_seq_nextval` -- ---------------------------- DROP FUNCTION IF EXISTS `mycat_seq_nextval`; DELIMITER ;; CREATE DEFINER=`root`@`%` 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 ; -- ---------------------------- -- Function structure for `mycat_seq_setval` -- ---------------------------- 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 utf8 DETERMINISTIC BEGIN UPDATE MYCAT_SEQUENCE SET current_value = value WHERE name = seq_name; RETURN mycat_seq_currval(seq_name); END ;; DELIMITER ;
2.db2分片脚本
/* Navicat MySQL Data Transfer Source Server : mysql Source Server Version : 50527 Source Host : localhost:3306 Source Database : db2 Target Server Type : MYSQL Target Server Version : 50527 File Encoding : 65001 Date: 2016-01-27 15:48:50 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `company` -- ---------------------------- DROP TABLE IF EXISTS `company`; CREATE TABLE `company` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of company -- ---------------------------- -- ---------------------------- -- Table structure for `customer` -- ---------------------------- DROP TABLE IF EXISTS `customer`; CREATE TABLE `customer` ( `ID` bigint(20) NOT NULL DEFAULT '0', `sharding_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of customer -- ---------------------------- INSERT INTO `customer` VALUES ('2', null); INSERT INTO `customer` VALUES ('5', '10010'); -- ---------------------------- -- Table structure for `employee` -- ---------------------------- DROP TABLE IF EXISTS `employee`; CREATE TABLE `employee` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of employee -- ---------------------------- -- ---------------------------- -- Table structure for `goods` -- ---------------------------- DROP TABLE IF EXISTS `goods`; CREATE TABLE `goods` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of goods -- ---------------------------- INSERT INTO `goods` VALUES ('11'); -- ---------------------------- -- Table structure for `hotnews` -- ---------------------------- DROP TABLE IF EXISTS `hotnews`; CREATE TABLE `hotnews` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of hotnews -- ---------------------------- INSERT INTO `hotnews` VALUES ('1'); -- ---------------------------- -- Table structure for `orders` -- ---------------------------- DROP TABLE IF EXISTS `orders`; CREATE TABLE `orders` ( `ID` bigint(20) NOT NULL DEFAULT '0', `customer_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of orders -- ---------------------------- INSERT INTO `orders` VALUES ('2', '2'); INSERT INTO `orders` VALUES ('5', '5'); -- ---------------------------- -- Table structure for `travelrecord` -- ---------------------------- DROP TABLE IF EXISTS `travelrecord`; CREATE TABLE `travelrecord` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of travelrecord -- ---------------------------- INSERT INTO `travelrecord` VALUES ('2');
3.db3分片脚本
/* Navicat MySQL Data Transfer Source Server : mysql Source Server Version : 50527 Source Host : localhost:3306 Source Database : db3 Target Server Type : MYSQL Target Server Version : 50527 File Encoding : 65001 Date: 2016-01-27 15:48:58 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `company` -- ---------------------------- DROP TABLE IF EXISTS `company`; CREATE TABLE `company` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of company -- ---------------------------- -- ---------------------------- -- Table structure for `hotnews` -- ---------------------------- DROP TABLE IF EXISTS `hotnews`; CREATE TABLE `hotnews` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of hotnews -- ---------------------------- INSERT INTO `hotnews` VALUES ('2'); -- ---------------------------- -- Table structure for `travelrecord` -- ---------------------------- DROP TABLE IF EXISTS `travelrecord`; CREATE TABLE `travelrecord` ( `ID` bigint(20) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of travelrecord -- ---------------------------- INSERT INTO `travelrecord` VALUES ('3');
分别在两个读写库中建立三个分片
schema.xml中配置读写分离
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://org.opencloudb/"> <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"> <!-- auto sharding by id (long) --> <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /> <!-- global table is auto cloned to all defined data nodes ,so can join with any table whose sharding node is in the same data node --> <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" /> <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" /> <!-- random sharding using mod sharind rule --> <table name="hotnews" primaryKey="ID" dataNode="dn1,dn2,dn3" rule="mod-long" /> <table name="employee" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile" /> <table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile"> <childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id"> </childTable> </table> <table name="mycat_sequence" dataNode="dn1" /> </schema> <dataNode name="dn1" dataHost="localhost1" database="db1" /> <dataNode name="dn2" dataHost="localhost1" database="db2" /> <dataNode name="dn3" dataHost="localhost1" database="db3" /> <dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="hostM1" url="ip1:3306" user="root" password="123456"> <!-- can have multi read hosts --> <readHost host="hostS1" url="ip2:3306" user="root" password="123456" weight="1" /> </writeHost> </dataHost> </mycat:schema>
其中balance属性
负载均衡类型,目前取值有3种: 1. balance="0", 开启读写分离机制,所有读操作都发送到当前可用的writeHost上。 2. balance="1",全部的readHost和stand by writeHost参与select语句的负载均衡 3. balance="2",所有读操作都随机在writeHost、readhost上分发。 4. balance="3",所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力
以上ip1,ip2分别填写真实地址
测试读写分离
启动mycat服务,
测试读数据:select * from travelrecord
可见数据是从读库中读取
测试写数据:insert into travelrecord (ID) values(88)
查看读库,没值,写库有一条88的记录