我家很管事的猫——mycat初步部署实践与问题排查

mycat,阿里出品的mysql中间件,提供读写分离和分库分表方案。项目中主要使用的是其读写分离功能。html

【如何部署?】前端

本文只采用并测试了双主从模式,配置看这一篇足矣:mysql

https://www.cnblogs.com/biglittleant/p/7059569.htmlspring

须要注意在配置并启动mycat以前必定要完成mysql物理节点之间主从复制配置,并保证每一个节点show slave status\G中sql

SLAVE_SQL_RUNNING、SLAVE_IO_RUNNING都为YES。数据库

而后启动mycat,通常不会发生问题。服务器

对dataHost的三个参数进行解读:mybatis

<dataHost name="mysqlms" maxCon="2000" minCon="20" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">负载均衡

其中,balance指的负载均衡类型。async

1. balance="0", 不开启读写分离机制,全部读操做都发送到当前可用的writeHost上。

2. balance="1",所有的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,而且M1与 M2互为主备),正常状况下,M2,S1,S2都参与select语句的负载均衡。

3. balance="2",全部读操做都随机的在writeHost、readhost上分发。

4. balance="3",全部读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力

writeType指写操做模式。

1. writeType=“0”, 全部写操做都发送到可用的writeHost上。
2. writeType=“1”,全部写操做都随机的发送到readHost。
3. writeType=“2”,全部写操做都随机的在writeHost、readhost分上发。

switchType指的是切换的模式。

1. switchType='-1' 表示不自动切换

2. switchType='1' 默认值,表示自动切换

3. switchType='2' 基于MySQL主从同步的状态决定是否切换,心跳语句为 show slave status

4. switchType='3'基于MySQL galary cluster的切换机制(适合集群),心跳语句为 show status like 'wsrep%'。

目前尚未尝试过双主节点同时挂掉的状况,switchType暂且使用了默认值。这里有待后续测试。

【日志级别】
/.../mycat/conf/log4j2.xml
<asyncRoot level="debug"

此时可以看到mycat负载路径,很实用。

另外附上mysql在配置文件my.cnf中打开bin日志和普通日志的方式,尤为是普通日志,配合mycat日志能够更好地理解读写分离实现过程。

普通
general_log=1

general_log_file=/usr/local/log/query.log

SHOW GLOBAL VARIABLES LIKE 'general%';(查看开启状态,如未成功查看mysql日志mysqld.log)

二进制
log_bin=mysql-bin

SHOW GLOBAL VARIABLES LIKE '%log%';(查看开启状态,如未成功查看mysql日志mysqld.log)

【监控】

这里我试用了mycat-eye,我的感受并非很好用,不少项是空白也不清楚怎么开启,但至少能够很方便的得到物理节点的心跳状态。

【节点down掉】

写节点down掉以后其读节点也会失效,通常状况下重连以后此主从仍会做为mycat集群中承担读任务的节点。
mysql的主从同步线程重启时间较长,估算约30秒,估计还会受期间发生的事务数量影响。
好处是节点down掉以后重连会自动同步(只要双主从初始配置正常),不用手动修改mysql主从复制配置。

【写主节点down掉】
mycat在检测到写主节点会尝试将主节点分配给写从节点。并在dnindex.properties记录,dataHost name=? 为0时表示M1,为1时表示M2。

注意:在down掉的写主节点从新链接或将mycat重启后此值依然不变。指定写主节点须要手动修改并重启mycat。

【偶发bug】
一、【数据不一致】mycat对于即时性高的事务支持是比较稳定的,测试中与代码执行逻辑相违背的数据不一致状况极偶发,其中**在写主节点down掉从新启动以后必发**。
未及时状况缘由:在mycat中,部分写sql发生在读sql以后。

二、down掉重启以后可能不会再将读请求分配给写从节点及其读从节点,这里可能涉及负载均衡策略,还需进一步测试。

【其余问题排查,mysql自己问题居多】

一、【navicat前端不能直接操做mycat?数据会不一致?】

这个问题比较具备迷惑性,经测试,navicat操做mycat节点时,sql与jdbc链接mycat执行的sql无异,都是先发送至mycat由其进行负载分配(可查看日志mycat.log验证),update语句在writeType=“0”的状况下必定由写主节点完成。

若是不经由mycat而直接在写节点或读节点操做,mycat不会造成日志。

后来查清当时之所造成这样的认知,是由于其中一个读节点,因为服务器上其余应用的日志文件迅速占满了空间而致使mysql主从同步的线程阻塞,而mycat并未发现异常,继续为此节点分配读任务,致使数据不一致。

解决方法腾出空间便可,无需对该节点mysql进行额外操做。

实际上,当其中一个节点出现磁盘空间已满这种问题时,在navicat链接mycat打开一个表,反复刷新就会发现数据不一致状况。

mycat可否发现出问题的读节点并将其排除,有待进一步研究。

二、【SLAVE_SQL_RUNNING、SLAVE_IO_RUNNING为NO】

(1)SLAVE_SQL_RUNNING为NO可单独尝试reset master;看可否生效。

(2)SLAVE_IO_RUNNING为NO

到主库上show master status查一下主库当前的gtid(Executed_Gtid_Set),
而后到从库执行下面命令:
reset master;
stop slave;
set global gtid_purged = 'xxxx'; -- 这里xxxx是主库的Executed_Gtid_Set,能够为空噢
start slave;

意思是从库同步时,丢弃现有主库执行过的gtid。

(3)以上若不能解决,看日志/var/log/mysqld.log对症下药。

对于网上的一些change master解决方式,在GTID模式开启的状况下,

gtid-mode=on
enforce-gtid-consistency

不用从新指定change master to master_log_file='mysql-bin.xxxxxx',master_log_pos=xxx;

 三、【我用navicat打开某个schema以后刷新,看到的“行”、“自动递增值”、“修改日期”不同?】

首先,这里的统计数据是由SHOW TABLE STATUS获得的。每一个表内的记录其实是彻底一致的。

(1)“行”:这里引用CSDN论坛小小小小周的回答:

“部分存储引擎,如MyISAM,存储精确的数目。
对于其它存储引擎,好比InnoDB,本值是一个大约的数,与实际值相差可达40到50%。在这些状况下,使用SELECT COUNT(*)来得到准确的数目。
对于在INFORMATION_SCHEMA数据库中的表,Rows值为NULL”

(2)“自动递增值”:在,除了主写节点之外,其余承担读任务的节点increment应该都一致并比主写节点少1。

(increment能够经过 SELECT auto_increment FROM information_schema.tables where table_schema="dbName" and table_name="tableName";单独查看,值和SHOW TABLE STATUS获得的相同。)

查看my.cnf中的配置,两个写节点(或称M节点)的offset一个为1另外一个为2。

auto-increment-offset=x
auto-increment-increment=2

为了实现双主从模式的事务控制和切换,increment设置为2。由此致使主写节点比当前存在的最大一个id多2,其余节点(同步本身的主节点)比当前存在的最大一个id多1,注意这里设置了increment为2的另外一写节点一样比当前存在的最大一个id多1。

另猜想,**在写主节点down掉从新启动以后必发**的数据不一致bug可能与此有关,有待进一步测试。

(3)“修改日期”:这个值应该只有微小不一致,由于各节点主从同步时间有微小差异。固然,这里的信息都不彻底准确。

不当之处恳请各位指教,下篇jenkins。

【190103补充】

经测试,update等DML操做能够正常加行锁,而select...for update被mycat视做普通select,也就是说不会把select...for update分配到主写节点。

可是,在使用mybatis+spring的状况下,在select方法上加@Transaction注解(若是写在更外层则不会影响select方法)能够由主写节点处理查询,这时select...for update便可正常加锁了。

相关文章
相关标签/搜索