枚举分片
实验失败(ERROR 1064 (HY000): can’t find any valid datanode :TB_USER -> STATUS -> 2)
-
介绍
通过在配置文件中配置可能的枚举值, 指定数据分布到不同数据节点上, 本规则适用于按照省份、性别、状态拆分数据等业务 。
-
配置
schema.xml逻辑表配置:<!-- 枚举 --> <table name="tb_user" dataNode="dn4,dn5,dn6" rule="sharding-by-intfile-enumstatus"/>
schema.xml数据节点配置:
<dataNode name="dn4" dataHost="dhost1" database="itcast" /> <dataNode name="dn5" dataHost="dhost2" database="itcast" /> <dataNode name="dn6" dataHost="dhost3" database="itcast" />
rule.xml分片规则配置:
<tableRule name="sharding-by-intfile"> <rule> <columns>sharding_id</columns> <algorithm>hash-int</algorithm> </rule> </tableRule> <!-- 自己增加 tableRule --> <tableRule name="sharding-by-intfile-enumstatus"> <rule> <columns>status</columns> <algorithm>hash-int</algorithm> </rule> </tableRule> <function name="hash-int" class="io.mycat.route.function.PartitionByFileMap"> <property name="defaultNode">2</property> <property name="mapFile">partition-hash-int.txt</property> </function>
partition-hash-int.txt
,内容如下 :#左边表示枚举值,右边表示具体的数据节点 1=0 2=1 3=2
分片规则属性说明如下:
属性 描述 columns 标识将要分片的表字段 algorithm 指定分片函数与function的对应关系 class 指定该分片算法对应的类 mapFile 对应的外部配置文件 type 默认值为0 ; 0 表示Integer , 1 表示String defaultNode 默认节点 ; 小于0 标识不设置默认节点 , 大于等于0代表设置默认节点 ;默认节点的使用:枚举分片时,如果碰到不识别的枚举值, 就让它路由到默认节点 ; 如果没有默认值,碰到不识别的则报错 。 该分片规则,主要是针对于数字类型的字段适用。 在前面水平拆分的演示中,我们选择的就是取模分片。
补充:模运算,大模小,结果为大除于小的余数;小模大,直接返回小值
-
测试
配置完毕后,重新启动MyCat,然后在mycat的命令行中,执行如下SQL创建表、并插入数据,查看数据分布情况。CREATE TABLE tb_user ( id bigint(20) NOT NULL COMMENT 'ID', username varchar(200) DEFAULT NULL COMMENT '姓名', status int(2) DEFAULT '1' COMMENT '1:未启用, 2:已启用, 3:已关闭', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; insert into tb_user (id,username ,status) values(1,'Tom',1); insert into tb_user (id,username ,status) values(2,'Cat',2); insert into tb_user (id,username ,status) values(3,'Rose',3); insert into tb_user (id,username ,status) values(4,'Coco',2); insert into tb_user (id,username ,status) values(5,'Lily',1); insert into tb_user (id,username ,status) values(6,'Tom',1); insert into tb_user (id,username ,status) values(7,'Cat',2); insert into tb_user (id,username ,status) values(8,'Rose',3); insert into tb_user (id,username ,status) values(9,'Coco',2); insert into tb_user (id,username ,status) values(10,'Lily',1);
应用指定算法
-
介绍
运行阶段由应用自主决定路由到那个分片 , 直接根据字符子串(必须是数字)计算分片号。
-
配置
schema.xml逻辑表配置:<!-- 应用指定算法 --> <table name="tb_app" dataNode="dn4,dn5,dn6" rule="sharding-by-substring" />
schema.xml数据节点配置:
<dataNode name="dn4" dataHost="dhost1" database="itcast" /> <dataNode name="dn5" dataHost="dhost2" database="itcast" /> <dataNode name="dn6" dataHost="dhost3" database="itcast" />
rule.xml分片规则配置:
<tableRule name="sharding-by-substring"> <rule> <columns>id</columns> <algorithm>sharding-by-substring</algorithm> </rule> </tableRule> <function name="sharding-by-substring" class="io.mycat.route.function.PartitionDirectBySubString"> <property name="startIndex">0</property> <!-- zero-based --> <property name="size">2</property> <property name="partitionCount">3</property> <property name="defaultPartition">0</property> </function>
分片规则属性说明如下:
属性 描述 columns 标识将要分片的表字段 algorithm 指定分片函数与function的对应关系 class 指定该分片算法对应的类 startIndex 字符子串起始索引 size 字符长度 partitionCount 分区(分片)数量 defaultPartition 默认分片(在分片数量定义时, 字符标示的分片编号不在分片数量内时,使用默认分片) 示例说明 :
id=05-100000002 , 在此配置中代表根据id中从 startIndex=0,开始,截取siz=2位数字即05,05就是获取的分区,如果没找到对应的分片则默认分配到defaultPartition 。 -
测试
配置完毕后,重新启动MyCat,然后在mycat的命令行中,执行如下SQL创建表、并插入数据,查看数据分布情况。CREATE TABLE tb_app ( id varchar(10) NOT NULL COMMENT 'ID', name varchar(200) DEFAULT NULL COMMENT '名称', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; insert into tb_app (id,name) values('0000001','Testx00001'); insert into tb_app (id,name) values('0100001','Test100001'); insert into tb_app (id,name) values('0100002','Test200001'); insert into tb_app (id,name) values('0200001','Test300001'); insert into tb_app (id,name) values('0200002','TesT400001');
固定分片hash算法
-
介绍
该算法类似于十进制的求模运算,但是为二进制的操作,例如,取 id 的二进制低 10 位 与1111111111 进行位 & 运算,位与运算最小值为 0000000000,最大值为1111111111,转换为十进制,也就是位于0-1023之间。
特点:- 如果是求模,连续的值,分别分配到各个不同的分片;但是此算法会将连续的值可能分配到相同的分片,降低事务处理的难度。
- 可以均匀分配,也可以非均匀分配。
- 分片字段必须为数字类型。
-
配置
schema.xml逻辑表配置:<!-- 固定分片hash算法 --> <table name="tb_longhash" dataNode="dn4,dn5,dn6" rule="sharding-by-long-hash" />
schema.xml数据节点配置:
<dataNode name="dn4" dataHost="dhost1" database="itcast" /> <dataNode name="dn5" dataHost="dhost2" database="itcast" /> <dataNode name="dn6" dataHost="dhost3" database="itcast" />
rule.xml分片规则配置:
<tableRule name="sharding-by-long-hash"> <rule> <columns>id</columns> <algorithm>sharding-by-long-hash</algorithm> </rule> </tableRule> <!-- 分片总长度为1024,count与length数组长度必须一致; --> <function name="sharding-by-long-hash" class="io.mycat.route.function.PartitionByLong"> <property name="partitionCount">2,1</property> <property name="partitionLength">256,512</property> </function>
分片规则属性说明如下:
属性 描述 columns 标识将要分片的表字段 algorithm 指定分片函数与function的对应关系 class 指定该分片算法对应的类 partitionCount 分片个数数组,2,1表示定义前两个节点和后一个节点 partitionLength 分片范围数组与partitionCount对应,
256,512表示前两个节点分片长度为256,后一个节点分片长度为512约束 :
-
) 分片长度 : 默认最大2^10 , 为 1024 ;
-
) count, length的数组长度必须是一致的 ;
以上分为三个分区:0-255,256-511,512-1023
515 > 512 存放在第三个分组(序号为2)
-
-
测试
配置完毕后,重新启动MyCat,然后在mycat的命令行中,执行如下SQL创建表、并插入数据,查看数据分布情况。CREATE TABLE tb_longhash ( id int(11) NOT NULL COMMENT 'ID', name varchar(200) DEFAULT NULL COMMENT '名称', firstChar char(1) COMMENT '首字母', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; #存储数据到第一个分组 insert into tb_longhash (id,name,firstChar) values(1,'七匹狼','Q'); insert into tb_longhash (id,name,firstChar) values(2,'八匹狼','B'); insert into tb_longhash (id,name,firstChar) values(3,'九匹狼','J'); insert into tb_longhash (id,name,firstChar) values(4,'十匹狼','S'); insert into tb_longhash (id,name,firstChar) values(5,'六匹狼','L'); insert into tb_longhash (id,name,firstChar) values(6,'五匹狼','W'); insert into tb_longhash (id,name,firstChar) values(7,'四匹狼','S'); insert into tb_longhash (id,name,firstChar) values(8,'三匹狼','S'); insert into tb_longhash (id,name,firstChar) values(9,'两匹狼','L'); #存储数据到第二个分组 insert into tb_longhash (id, name, firstChar) values(269,'很多匹狼','L');
字符串hash解析算法
-
介绍
截取字符串中的指定位置的子字符串, 进行hash算法, 算出分片。
-
配置
schema.xml逻辑表配置:<!-- 字符串hash解析算法 --> <table name="tb_strhash" dataNode="dn4,dn5" rule="sharding-by-stringhash" />
schema.xml数据节点配置:
<dataNode name="dn4" dataHost="dhost1" database="itcast" /> <dataNode name="dn5" dataHost="dhost2" database="itcast" />
rule.xml分片规则配置:
<tableRule name="sharding-by-stringhash"> <rule> <columns>name</columns> <algorithm>sharding-by-stringhash</algorithm> </rule> </tableRule> <function name="sharding-by-stringhash" class="io.mycat.route.function.PartitionByString"> <property name="partitionLength">512</property> <!-- zero-based --> <property name="partitionCount">2</property> <property name="hashSlice">0:2</property><!-- 截取0、1、2三个下标所指定的字符 --> </function>
分片规则属性说明如下:
属性 描述 columns 标识将要分片的表字段 algorithm 指定分片函数与function的对应关系 class 指定该分片算法对应的类 partitionLength hash求模基数 ; length*count=1024 (出于性能考虑) partitionCount 分区(分片)数量 hashSlice hash运算位 , 根据子字符串的hash运算 ; 0 代表 str.length(), -1 代表 str.length()-1 , 大于0只代表数字自身 ; 可以理解为substring(start,end),start为0则只表示0 示例说明 :
-
测试
配置完毕后,重新启动MyCat,然后在mycat的命令行中,执行如下SQL创建表、并插入数据,查看数据分布情况。create table tb_strhash( name varchar(20) primary key, content varchar(100) )engine=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO tb_strhash (name,content) VALUES('T1001', UUID()); INSERT INTO tb_strhash (name,content) VALUES('ROSE', UUID()); INSERT INTO tb_strhash (name,content) VALUES('JERRY', UUID()); INSERT INTO tb_strhash (name,content) VALUES('CRISTINA', UUID()); INSERT INTO tb_strhash (name,content) VALUES('TOMCAT', UUID());
按天分片算法
-
介绍
按照日期及对应的时间周期来分片。
-
配置
schema.xml逻辑表配置:<!-- 按天分片 --> <table name="tb_datepart" dataNode="dn4,dn5,dn6" rule="sharding-by-date" />
schema.xml数据节点配置:
<dataNode name="dn4" dataHost="dhost1" database="itcast" /> <dataNode name="dn5" dataHost="dhost2" database="itcast" /> <dataNode name="dn6" dataHost="dhost3" database="itcast" />
rule.xml分片规则配置:
<tableRule name="sharding-by-date"> <rule> <columns>create_time</columns> <algorithm>sharding-by-date</algorithm> </rule> </tableRule> <function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate"> <property name="dateFormat">yyyy-MM-dd</property> <property name="sBeginDate">2022-01-01</property> <property name="sEndDate">2022-01-30</property> <property name="sPartionDay">10</property> </function> <!-- 从开始时间开始,每10天为一个分片,到达结束时间之后,会重复开始分片插入 配置表的 dataNode 的分片,必须和分片规则数量一致,例如 2022-01-01 到 2022-12-31 ,每 10天一个分片,一共需要37个分片。 -->
分片规则属性说明如下:
属性 描述 columns 标识将要分片的表字段 algorithm 指定分片函数与function的对应关系 class 指定该分片算法对应的类 dateFormat 日期格式 sBeginDate 开始日期 sEndDate 结束日期,如果配置了结束日期,则代码数据到达了这个日期的分片后,会重复从开始分片插入 sPartionDay 分区天数,默认值 10 ,从开始日期算起,每隔10天一个分区 -
测试
配置完毕后,重新启动MyCat,然后在mycat的命令行中,执行如下SQL创建表、并插入数据,查看数据分布情况。create table tb_datepart( id bigint not null comment 'ID' primary key, name varchar(100) null comment '姓名', create_time date null ); insert into tb_datepart(id,name ,create_time) values(1,'Tom','2022-01-01'); insert into tb_datepart(id,name ,create_time) values(2,'Cat','2022-01-10'); insert into tb_datepart(id,name ,create_time) values(3,'Rose','2022-01-11'); insert into tb_datepart(id,name ,create_time) values(4,'Coco','2022-01-20'); insert into tb_datepart(id,name ,create_time) values(5,'Rose2','2022-01-21'); insert into tb_datepart(id,name ,create_time) values(6,'Coco2','2022-01-30'); insert into tb_datepart(id,name ,create_time) values(7,'Coco3','2022-01-31');
- 2022-01-30会被存放在第三个节点,2022-01-31的数据会被存放到第一个节点
自然月分片
-
介绍
使用场景为按照月份来分片, 每个自然月为一个分片。
-
配置
schema.xml逻辑表配置:<!-- 按自然月分片 --> <table name="tb_monthpart" dataNode="dn4,dn5,dn6" rule="sharding-by-month" />
schema.xml数据节点配置:
<dataNode name="dn4" dataHost="dhost1" database="itcast" /> <dataNode name="dn5" dataHost="dhost2" database="itcast" /> <dataNode name="dn6" dataHost="dhost3" database="itcast" />
rule.xml分片规则配置:
<tableRule name="sharding-by-month"> <rule> <columns>create_time</columns> <algorithm>partbymonth</algorithm> </rule> </tableRule> <function name="partbymonth" class="io.mycat.route.function.PartitionByMonth"> <property name="dateFormat">yyyy-MM-dd</property> <property name="sBeginDate">2022-01-01</property> <property name="sEndDate">2022-03-31</property> </function> <!-- 从开始时间开始,一个月为一个分片,到达结束时间之后,会重复开始分片插入 配置表的 dataNode 的分片,必须和分片规则数量一致,例如 2022-01-01 到 2022-12-31 ,一 共需要12个分片。 -->
分片规则属性说明如下:
属性 描述 columns 标识将要分片的表字段 algorithm 指定分片函数与function的对应关系 class 指定该分片算法对应的类 dateFormat 日期格式 sBeginDate 开始日期 sEndDate 结束日期,如果配置了结束日期,则代码数据到达了这个日期的分片后,会重复从开始分片插入 -
测试
配置完毕后,重新启动MyCat,然后在mycat的命令行中,执行如下SQL创建表、并插入数据,查看数据分布情况。create table tb_monthpart( id bigint not null comment 'ID' primary key, name varchar(100) null comment '姓名', create_time date null ); insert into tb_monthpart(id,name ,create_time) values(1,'Tom','2022-01-01'); insert into tb_monthpart(id,name ,create_time) values(2,'Cat','2022-01-10'); insert into tb_monthpart(id,name ,create_time) values(3,'Rose','2022-01-31'); insert into tb_monthpart(id,name ,create_time) values(4,'Coco','2022-02-20'); insert into tb_monthpart(id,name ,create_time) values(5,'Rose2','2022-02-25'); insert into tb_monthpart(id,name ,create_time) values(6,'Coco2','2022-03-10'); insert into tb_monthpart(id,name ,create_time) values(7,'Coco3','2022-03-31'); insert into tb_monthpart(id,name ,create_time) values(8,'Coco4','2022-04-10'); insert into tb_monthpart(id,name ,create_time) values(9,'Coco5','2022-04-30');
- 1、4月份的数据会被存放在第一个数据节点,3月份的数据会被存放在第三个数据节点
MyCat管理及监控
MyCat原理
在MyCat中,当执行一条SQL语句时,MyCat需要进行SQL解析、分片分析、路由分析、读写分离分析等操作,最终经过一系列的分析决定将当前的SQL语句到底路由到那几个(或哪一个)节点数据库,数据库将数据执行完毕后,如果有返回的结果,则将结果返回给MyCat,最终还需要在MyCat中进行结果合并、聚合处理、排序处理、分页处理等操作,最终再将结果返回给客户端。
- 一般的:在上面的这个例子中,如果查询语句有指定关于
status
字段(也就是设置的分片字段)的查询条件,路由会规则指定到特定的数据节点- 该情况描述同样适用与
status
的多查询
- 该情况描述同样适用与
- 特别的:如果没有指定
status
字段的查询条件,路由会使下面的所有分片节点都接收到这条查询语句
而在MyCat的使用过程中,MyCat官方也提供了一个管理监控平台MyCat-Web(MyCat-eye)。Mycat-web 是 Mycat 可视化运维的管理和监控平台,弥补了 Mycat 在监控上的空白。帮 Mycat分担统计任务和配置管理任务。Mycat-web 引入了 ZooKeeper 作为配置中心,可以管理多个节点。Mycat-web 主要管理和监控 Mycat 的流量、连接、活动线程和内存等,具备 IP 白名单、邮件告警等模块,还可以统计 SQL 并分析慢 SQL 和高频 SQL 等。为优化 SQL 提供依据。
MyCat管理
Mycat默认开通2个端口,可以在server.xml中进行修改。
- 8066 数据访问端口,即进行 DML 和 DDL 操作。
- 9066 数据库管理端口,即 mycat 服务管理控制功能,用于管理mycat的整个集群状态
连接MyCat的管理控制台:
mysql -h 192.168.200.210 -P 9066 -uroot -p12345
命令 | 含义 |
---|---|
show @@help | 查看Mycat管理工具帮助文档 |
show @@version | 查看Mycat的版本 |
reload @@config | 重新加载Mycat的配置文件 |
show @@datasource | 查看Mycat的数据源信息 |
show @@datanode | 查看MyCat现有的分片节点信息 |
show @@threadpool | 查看Mycat的线程池信息 |
show @@sql | 查看执行的SQL |
show @@sql.sum | 查看执行的SQL统计 |
MyCat-eye
Mycat-web(Mycat-eye)是对mycat-server提供监控服务,功能不局限于对mycat-server使用。他通过JDBC连接对Mycat、Mysql监控,监控远程服务器(目前仅限于linux系统)的cpu、内存、网络、磁盘。
Mycat-eye运行过程中需要依赖zookeeper,因此需要先安装zookeeper。
安装详见相关的安装文档
补充:**JDBC的全称是Java数据库连接(Java Database connect),它是一套用于执行SQL语句的Java API。应用程序可通过这套API连接到关系数据库,并使用SQL语句来完成对数据库中数据的查询、更新和删除等操作。**应用程序使用JDBC访问数据库的方式如下图所示。
访问
http://192.168.56.128:8082/mycat
配置
- 开启MyCat的实时统计功能(server.xml)
<property name="useSqlStat">1</property> <!-- 1为开启实时统计、0为关闭 -->
- 在Mycat监控界面配置服务地址
测试
配置好了之后,我们可以通过MyCat执行一系列的增删改查的测试,然后过一段时间之后,打开mycat-eye的管理界面,查看mycat-eye监控到的数据信息。
- 可以使用性能监控、物理节点、SQL统计、SQL表分析、SQL监控、高频SQL等功能
读写分离
读写分离,简单地说是把对数据库的读和写操作分开,以对应不同的数据库服务器。主数据库提供写操作,从数据库提供读操作,这样能有效地减轻单台数据库的压力。
通过MyCat即可轻易实现上述功能,不仅可以支持MySQL,也可以支持Oracle和SQL Server。
一主一从
原理
MySQL的主从复制,是基于二进制日志(binlog)实现的。
准备
主机 | 角色 | 用户名 | 密码 |
---|---|---|---|
192.168.200.211 | master | root | 1234 |
192.168.200.212 | slave | root | 1234 |
备注:主从复制的搭建,可以参考前面笔记中 主从复制 小结分析的步骤操作。
schema.xml配置
<!-- 配置逻辑库;逻辑表可以不指定,会自动加载所在数据节点所在的数据库,然后读取这个数据库中所有的表结构来作为逻辑表 -->
<schema name="ITCAST_RW" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn7">
</schema>
<dataNode name="dn7" dataHost="dhost7" database="itcast" />
<dataHost name="dhost7" maxCon="1000" minCon="10" balance="1" writeType="0"
dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="master1" url="jdbc:mysql://192.168.200.211:3306?
useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8"
user="root" password="1234" >
<readHost host="slave1" url="jdbc:mysql://192.168.200.212:3306?
useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8"
user="root" password="1234" />
</writeHost>
</dataHost>
<!-- 实践完成的用例 -->
<schema name="ITCAST_RW" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn7">
</schema>
<dataNode name="dn7" dataHost="dhost7" database="itcast" />
<dataHost name="dhost7" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="master" url="jdbc:mysql://192.168.56.134:3306?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8" user="root"
password="123321">
<readHost host="slave" url="jdbc:mysql://192.168.56.133:3306?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8" user="root"
password="123321">
</readHost>
</writeHost>
</dataHost>
测试
配置完毕MyCat后,重新启动MyCat。
user> bin/mycat stop
user> bin/mycat start
然后观察,在执行增删改操作时,对应的主库及从库的数据变化。 在执行查询操作时,检查主库及从
库对应的数据变化。
观察的办法是,由于先去已经配置过主从复制,从库的数据不会同步到主库的数据中去,更改从库数据,可以看出在mycat中查询出来的为从库的数据,插入语句操作的是主库(因为插入后主库和从库都存在数据)
在测试中,我们可以发现当主节点Master宕机之后,业务系统就只能够读,而不能写入数据了。
双主双从
一个主机 Master1 用于处理所有写请求,它的从机 Slave1 和另一台主机 Master2 还有它的从机 Slave2 负责所有读请求。当 Master1 主机宕机后,Master2 主机负责写请求,Master1 、Master2 互为备机。架构图如下:
准备
我们需要准备5台服务器,具体的服务器及软件安装情况如下:
编号 | IP | 预装软件 | 角色 |
---|---|---|---|
1 | 192.168.200.210 | MyCat、MySQL MyCat中间件服务器 | |
2 | 192.168.200.211 | MySQL | M1 |
3 | 192.168.200.212 | MySQL | S1 |
4 | 192.168.200.213 | MySQL | M2 |
5 | 192.168.200.214 | MySQL | S2 |
M1、S1和M2、S2分别建立主从同步关系
#关闭以上所有服务器的防火墙:
user> systemctl stop firewalld
user> systemctl disable firewalld
搭建
主库配置
-
Master1(192.168.200.211)
-
修改配置文件 /etc/my.cnf
#mysql 服务ID,保证整个集群环境中唯一,取值范围:1 – 2^32-1,默认为1 server-id=1 #设备1;server-id=3 #设备3 按各自的编号设置server-id #指定同步的数据库 binlog-do-db=db01 binlog-do-db=db02 binlog-do-db=db03 #在作为从数据库的时候,有写入操作也要更新二进制日志文件 log-slave-updates
-
重启MySQL服务器
user> systemctl restart mysqld
-
创建账户并授权
#创建itcast用户,并设置密码,该用户可在任意主机连接该MySQL服务 mysql> CREATE USER 'itcast'@'%' IDENTIFIED WITH mysql_native_password BY 'Root@123456'; #为 'itcast'@'%' 用户分配主从复制权限 mysql> GRANT REPLICATION SLAVE ON *.* TO 'itcast'@'%';
通过指令,查看两台主库的二进制日志坐标
mysql> show master status ;
-
-
Master2(192.168.200.211)
-
修改配置文件 /etc/my.cnf
#mysql 服务ID,保证整个集群环境中唯一,取值范围:1 – 2^32-1,默认为1 server-id=1 #设备1;server-id=3 #设备3 按各自的编号设置server-id #指定同步的数据库 binlog-do-db=db01 binlog-do-db=db02 binlog-do-db=db03 #在作为从数据库的时候,有写入操作也要更新二进制日志文件 log-slave-updates
-
重启MySQL服务器
user> systemctl restart mysqld
-
创建账户并授权
#创建itcast用户,并设置密码,该用户可在任意主机连接该MySQL服务 mysql> CREATE USER 'itcast'@'%' IDENTIFIED WITH mysql_native_password BY 'Root@123456'; #为 'itcast'@'%' 用户分配主从复制权限 mysql> GRANT REPLICATION SLAVE ON *.* TO 'itcast'@'%';
通过指令,查看两台主库的二进制日志坐标
mysql> show master status;
-
从库配置
-
Slave1(192.168.200.212)
-
修改配置文件 /etc/my.cnf
#mysql 服务ID,保证整个集群环境中唯一,取值范围:1 – 232-1,默认为1 server-id=4
-
重启MySQL服务器
user> systemctl restart mysqld
-
-
Slave2(192.168.200.214)
-
修改配置文件 /etc/my.cnf
#mysql 服务ID,保证整个集群环境中唯一,取值范围:1 – 232-1,默认为1 server-id=4
-
重启MySQL服务器
user> systemctl restart mysqld
-
从库关联主库
-
两台从库配置关联的主库
需要注意slave1对应的是master1,slave2对应的是master2。
-
在 slave1(192.168.200.212)上执行
CHANGE MASTER TO MASTER_HOST='192.168.200.211', MASTER_USER='itcast',MASTER_PASSWORD='Root@123456', MASTER_LOG_FILE='binlog.000002',MASTER_LOG_POS=663;
-
在 slave2(192.168.200.214)上执行
CHANGE MASTER TO MASTER_HOST='192.168.200.213', MASTER_USER='itcast',MASTER_PASSWORD='Root@123456', MASTER_LOG_FILE='binlog.000002',MASTER_LOG_POS=663;
-
启动两台从库主从复制,查看从库状态
start slave; show slave status \G;
-
-
两台主库相互复制
Master2 复制 Master1,Master1 复制 Master2。
-
在 Master1(192.168.200.211)上执行
CHANGE MASTER TO MASTER_HOST='192.168.200.213', MASTER_USER='itcast',MASTER_PASSWORD='Root@123456', MASTER_LOG_FILE='binlog.000002',MASTER_LOG_POS=663;
-
在 Master2(192.168.200.213)上执行
CHANGE MASTER TO MASTER_HOST='192.168.200.211', MASTER_USER='itcast',MASTER_PASSWORD='Root@123456', MASTER_LOG_FILE='binlog.000002',MASTER_LOG_POS=663;
-
启动两台从库主从复制,查看从库状态
start slave; show slave status \G;
-
经过上述的三步配置之后,双主双从的复制结构就已经搭建完成了。 接下来,我们可以来测试验证一下。
测试
分别在两台主库Master1、Master2上执行DDL、DML语句,查看涉及到的数据库服务器的数据同步情况。
create database db01;
use db01;
create table tb_user(
id int(11) not null,
name varchar(50) not null,
sex varchar(1),
primary key (id)
)engine=innodb default charset=utf8;
insert into tb_user(id,name,sex) values(1,'Tom','1');
insert into tb_user(id,name,sex) values(2,'Trigger','0');
insert into tb_user(id,name,sex) values(3,'Dawn','1');
insert into tb_user(id,name,sex) values(4,'Jack Ma','1');
insert into tb_user(id,name,sex) values(5,'Coco','0');
insert into tb_user(id,name,sex) values(6,'Jerry','1');
- 在Master1中执行DML、DDL操作,看看数据是否可以同步到另外的三台数据库中。
- 在Master2中执行DML、DDL操作,看看数据是否可以同步到另外的三台数据库中。
完成了上述双主双从的结构搭建之后,接下来,我们再来看看如何完成这种双主双从的读写分离。
双主双从读写分离
配置
MyCat控制后台数据库的读写分离和负载均衡由schema.xml文件datahost标签的balance属性控制,通过writeType及switchType来完成失败自动切换的。
-
schema.xml
配置逻辑库:<schema name="ITCAST_RW2" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn7"> </schema>
配置数据节点:
<dataNode name="dn7" dataHost="dhost7" database="db01" />
配置节点主机:
<dataHost name="dhost7" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <writeHost host="master1" url="jdbc:mysql://192.168.56.134:3306?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8" user="root" password="123321" > <readHost host="slave1" url="jdbc:mysql://192.168.56.133:3306?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8" user="root" password="123321" /> </writeHost> <writeHost host="master2" url="jdbc:mysql://192.168.56.137:3306?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8" user="root" password="123321" > <readHost host="slave2" url="jdbc:mysql://192.168.56.136:3306?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8" user="root" password="123321" /> </writeHost> </dataHost>
具体的对应情况如下:
属性说明:
<--! 负载均衡策略 --> balance="1" 代表全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载均衡 ; <--! 指定写入机制 --> writeType 0 : 写操作都转发到第1台writeHost, writeHost1挂了, 会切换到writeHost2上; 1 : 所有的写操作都随机地发送到配置的writeHost上 ; <--! 控制是否自动切换 --> switchType -1 : 不自动切换 1 : 自动切换
-
user.xml
配置root用户也可以访问到逻辑库 ITCAST_RW2。<user name="root" defaultAccount="true"> <property name="password">123321</property> <property name="schemas">SHOPPING,ITCAST,ITCAST_RW2</property> <!-- 表级 DML 权限设置 --> <!-- <privileges check="false"> <schema name="TESTDB" dml="0110" > <table name="tb01" dml="0000"></table> <table name="tb02" dml="1111"></table> </schema> </privileges> --> </user>
测试
登录MyCat,测试查询及更新操作,判定是否能够进行读写分离,以及读写分离的策略是否正确。
观察,在执行增删改操作时,对应的主库及从库的数据变化。 在执行查询操作时,检查主库及从库对应的数据变化。
-
观察的办法是,由于先去已经配置过主从复制,从库的数据不会同步到主库的数据中去,更改从库数据,可以看出在mycat中查询出来的为从库的数据,插入语句操作的是主库(因为插入后主库和从库都存在数据)
-
当主库挂掉一个之后,是否能够自动切换。
MySQL主从复制是基于二进制日志binlog实现的。master、slave
master数据一旦发生变更,数据变更写入到二进制日志,
- slave节点会去读取master节点的二进制日志,
- 让后把读取过来的二进制日志写入到自身的中继日志,
- 然后再通过另外一组线程SQLThread去读取中继日志中的数据,
- 然后反应到自身的变化。
这么一来,master一旦有数据变更,就会同步到slave