掌握MGR使用场景和常见高可用方案问答

今天看到 sql server 的 merge join 和 hash join,mysql 也有吗?
A:mysql 有 hash join,从 8.0 开始,加入了这个特性,8.0 之前是没有的。没有 merge join,但是它的 join 在 5.7 及其以前,用的是嵌套循环(nested loop join)。在 mysql 里面,多表过来的时候,最好是两张,三张已经算很多了,再多的话,可能把数据库hang 死。

在 Docker 容器里面跑 mysql,上亿级别的数据合适吗,还是说要不停的分表?
A:我建议按照上亿级别的数据,在一个实例是可以放的。一个单表的上限也就是上亿级别的数据。当然了,一个实例里面,不止是一个表,(上亿级别的数据)完全是可以放的。

Mysql 在应用上相比 postgresql,有哪些逆势?
A:不好说,这是两种不同的关系性数据库,各有所长吧。在去 O 的场景中,替换 oracle 的话,pg 有原生的工具可以做数据迁移,以及语法上的兼容。用 mysql的话,需要手工去改存储过程、触发器等,让它语法兼容。但是在特定的场景下,比如 oltp,这样的场景下,mysql 的表现是要比 pg 好一点的,它是要分场景的。

MGR 多节点写这个是怎么保证的,还有自增字段的值如何保证?
A:多节点写,第一,如果说是多主模式下,分操作的:DDL 和 DML,如果是 DDL 的话,在同一个节点上,它是可以靠 mysql 内部一些锁的机制来保证冲突的;如果在不同的节点上操作,它可以通过内部的冲突检测机制,进行一个对比和核验。因为 mysql 底层的 paxos 协议,它就是保证了一个原子性的分布式协议。

Mysql 多写节点集群时,哪种解决方案更合适一些?
A:mysql 多节点的写适合哪些场景,不推荐在 8.0 里面用多写集群,因为在 8.0 里面,官方还有一些未知的 bug,而且多节点写入的话,ddl 这些操作在多个节点上执行,它可能引发一些未知的问题,发生什么的错误,我们不确定,所以官方也是在官方文档里面极力推荐用单主模式,多主模式是不推荐的,而且开了多主模式之后,多点写入,冲突检测机制更为复杂,还有一个问题就是,多主模式下,它的写性能要比单主模式还要差一些。

生产环境多主使用的多,还是单主使用的多,跟 pxc 有什么区别?
A:绝大多数的生产环境中,都是使用单主模式,我没有在生产上见过用多主模式的。pxc 我没有做过太深入的研究,因为我们用的是 mysql 官方的包。在生产上,对于 percona,它可能在某些场景下好一些,它和 pxc 的区别,在数据校验方面有一些不同,具体大家可以去看一下 pxc 的官方文档,我没有做太多太深入的研究。

Mgr 从节点延迟要怎么监控和计算?
A:在 perfomance schema 这个库里面有一些等待事件,还有一些表,表里面有具体的字段可以去查询,大家可以自行去 google,或者自己去看 perfomance schema 有关 mgr 参数的几张表,而且在官方的文档里面,有一节是专门对 mgr 的监控做了一个说明,这个里面有几张表,详细地说明了怎么去监控 mgr 的,包括节点的延迟(https://dev.mysql.com/doc/refman/8.0/en/group-replication-monitoring.html)。

什么是流控机制?
A:什么是流控机制,想象一下 mysql 用了 mgr 之后,集群的流量特别大,如果我们是在单主模式的情况下,在业务你写数据的时候,primary 节点和 secondary 节点的延迟会越来越大,越来越大,到达一定的阈值之后,secondary 节点会被自动踢出集群,流控机制的存在是为了限流,对整个集群做限流,以缩小 primary 节点和 secondary 节点事务之间的差距,保障我们集群最大的可用性。这就是流控机制,这里面分为了:可以限制冲突认证队列上事务数量的大小;还有就是限制 secondary 节点上面,应用事务队列的大小。

Mgr 现在生产上用的多吗?
A:mgr 现在生产上有用的,用的还不少,据我所知,在移动云上面,有个高可用集群用的是 mgr,还有一些互联网公司也在用 8.0,因为 mgr 到了 8.0 之后,它做了一个大幅度的改进,有很多我们在 5.7 里面只能用默认的一些参数,但它在 8.0 里面是可以自己控制的,而且互联网公司也越来越接受这项新技术。

Mgr 和 mha 相比,哪种以后较大的被称为高可用?
A:那肯定是 MGR。mha 在生产上有一个特别大的弊端,就是它真的会丢数据,它的那个代码逻辑问题,在我们进行高可用切换之后,它补 binlog 的那一段逻辑有问题,它在生产上确实也丢过数据。mgr 从 8.0 开始,变得稳定,也比较高效,从我个人的角度 来讲,非常有可能成为互联网公司里面很主流的高可用工具。

使用 mgr 单主模式,需要进行数据冲突检测吗?
A:它单主模式,有一个认证的过程,在单主模式里边,它一个事务想要在集群内提交,它必须要通过集群中大多数节点的认证,只有大多数从节点通过认证之后,它在类似于主从复制的 master 节点才能提交,大多数的节点代表着 n/2 + 1。它和简单的主从复制不一样,简单的主从复制的话,可能会出现数据一致性的问题,但是 mgr 它的出现,为什么它叫组复制,因为这个集群保障了整个集群内节点数据的强一致性,它在数据一致性方面,比其他的基于主从复制的高可用组件,强一点,但在整个集群的性能上面,因为它要维护一个数据冲突检测,还有流控等机制,可能需要消耗更多的 CPU 和内存,所以它的性能是比传统的主从复制稍微差那么一点点。mgr 的使用场景,就是那个典型的读写分离的场景下,mgr 实例上面加一个读写分离的中间件,它可以实现一个集群快速弹性的一个扩展。如果说你想要在传统的主从复制的场景下面,对集群进行一个扩容,或者是一个读的拓展,那你还得手动去搭一个实例,然后再把数据同步过去;如果用 mgr ,直接启动一个实例,然后用克隆插件,给它克隆,效率要高得高得多,而且会比较稳定。

Mysql 中间件 MaxScale 和 原理上有什么区别?
A:这个我觉得是仁者见仁智者见智吧。proxysql 本质上也是一个读写分离的。但是我觉得,相比于 maxscale 来说,我还是推荐 maxscale,生产上用 maxscale 的要多一些,而且比较成熟,这个东西。而且如果你用 maxscale,除了问题的话,它是有官方(mariadb)维护的,你可以去提 bug,基于它的用户,还可以在社区里面寻找到更多的帮助。proxysql 当然也有一定的用户,但是和 maxscale 相比,它的用户还是少了很多的。

刚才ppt 里面说的一致性校验那一块,如果说你 t1 和 t2 事务相互更新,它不会造成不一致?
A:比如说 t1 和 t2 这两条事务,更新的是同一条数据,在多主模式下,但是是在不同的节点执行的,这两个事务,谁先进入并通过冲突认证检测,谁就会成功提交,后进入冲突检测队列的那条事务,就会回滚。NDB 集群在国内没有人用,在国外可能有一些用户,我没有在国内生产环境上见过。这个就不要再用了,个人认为,ndb 和 mgr 没有可比性,一个两个节点还行,如果是五个七个九个节点,拓展得越多,集群的性能可能会被拖死的。用 mgr 当然是要用单主模式,你有分区表也不会有影响,没有关系的。生产环境,传统的主从复制和 mgr,如果说你对效率和性能有超级高的要求吧,我推荐你用传统的主从复制。从 5.7 有了并行复制,你开了并行复制之后,它的效率还是有很大的提升,如果你要求弹性扩容,拓展性强一些的话,对性能要求不是那么极端的话,可以用 mgr,维护起来也比较方便。

Mariadb 是 mysql 官方维护的。对 mysql 是兼容的,只管大胆的用就可以。

存储过程在实际的生产过程中,你原本的 mgr,在 mysql 单机或者主从复制里面,怎么去维护
换成了 mgr 之后,该怎么维护就怎么维护,不可能你换了一个架构,真个存储过程的维护的模式就变了,不是这样的。Mgr 感知主从切换,它的高可用切换的原理就是,在 mgr 的 primary 节点和 secondary 节点里面,所有的节点里面都维护这样一个属于自己的视图,这个视图里面记录了集群里面所有的节点,哪些节点是 onlien 状态,哪些节点是 offline 状态。如果说集群的状态有变更的话,会自动把自己维护的 mgr 集群的视图信息,通过原子广播协议,广播到了集群其他所有节点上面,有一个像心跳周期一样的保活机制:集群里面所有节点,会两两之间相互进行通信,他们就相互交流各自维护的集群的视图信息,如果说其中的 primary 节点宕了,立刻会把这个视图更新,然后发送到别的节点上面,而且别的节点也会近期的探测,如果它挂了的话,就会探测不到,探测不到,就会有相应的超时机制,内部就会进行一个选举。
Mgr 事务的机制,当然还是两阶段提交。这个 mgr 只是 mysql 内部提供的高可用的一个插件,它不会影响到了我们整个 mysql 事务的提交方式,你原来两阶段提交怎么提交,现在依旧怎么提交,只不过是事务在 server 层进行提交完之后,再到存储引擎层,正常你不用 mgr 的话,它在引擎层就是一个 commit;用了 mgr 的话,通过 server 层广播到了引擎层,它在存储引擎内部,它把这个事务下推到了 mgr 里面进行一个提交,还是 prepare + commit 两阶段提交。

在 mysql 里面你要建索引,建主键,那你最好要用一个跟业务没有关系的,自己的一个列来把它做成自增列,并且把它设置成 primary key 就可以了。第一好维护,第二如果业务有变更的话,不会影响你现有表一个主键的变更,易于维护。

把 innodb buffer pool 怎么去设置,需要有多大空间?
A:需要考虑你整个服务器的一个设置,innodb buffer pool 只需要,占到你底层的物理机或者虚拟机内存的 75% 左右就可以,不要太多,因为其他还要留给操作和我们自己的一些其他应用程序。buffer pool 75% 就可以。

为什么一个 mgr 集群最多支持九节点?
A:从我个人角度来讲,第一,原子广播协议,消息的传递和元数据信息的维护,本身也会对集群造成一个性能的降低和开销。如果无限拓展的话,集群的规模越大,整个集群的效率也会越低,到了一定的规模,它会严重影响整个集群的性能。如果说超过九个节点,你一条事务要提交,那么根据 mgr 的 2/n + 1 的原则,多数节点验证完成才能通过,你集群规模越大,那你事务提交的效率越低,违背了高可用设计的初衷。

Mgr 是支持水平扩容的,和 clone 插件搭配起来,它扩容是非常的快速,而且还非常的稳定。

Proxysql 也可以用,这个中间件也比较成熟。但是我个人更倾向于 maxscale,做读写分离这样的场景的话。这个审计插件,官方的就不推荐了,因为它太耗性能,可以这么去用,可以用 mysql proxy 结合 lua 脚本做数据库审计插件,在云厂商里面,它自己的 audit log 插件也是通过类似的这样一个思想去实现的,当然我指的是某一个云厂商,不是指全部。

Mysql 8.0 高可用架构,官方提供的只有 mgr,自己的那,各个公司有各个公司的。各种各样的高可用实现,有从底层存储下功夫,有通过 etcd 这样的分布式锁来实现高可用的,很多。

Mysql 的学习路线
首先要学会怎么去用,最基本的安装部署,以及里面一些常见的文件,用的熟了之后,可以研究一下里面的原理,从体系结构来研究它,比如它的 buffer pool,以及它的一个 io 调度机制,比如说 redo、undo、binlog 一些东西,比如它的一些 change buffer,double write 等等,比如它的 buffer pool 有什么用,可以由浅入深地去研究它。自己遇到问题,可以搭建一个带 debug 的环境去调试一下,感受一把 mysql 内部的工作原理。

Mysql 版本是更新挺频繁
8.0 里面,但是 mgr 它本身放出来之后,它已经趋于一个很稳定很成熟的一个,它后期不会再进行一个频繁地更新,只有出现严重的问题或 bug 的时候,才会出现频繁地更新,但是 mgr 已经很稳定了,并且它的一个性能已经有长足的改进,所有后期它针对一些小问题,过很长一段时间,会进行一个更新,不会像 8.0 里面一样,不断反复地一个更新,因为 8.0 里面加入了很多的新特性,应该很快会发布下一个大版本。
Mgr 的延迟监控,你要确定毫秒级别,秒级别,你可以去调整 perfomance schema 这个库里面,相应的监控,mgr 组件等待事件的粒度,一般来讲,你看 mgr 的监控,没有必要到毫秒级别,秒级别就管够了。
Mgr 跨机房网络,除非你可以保证你机房里,异地或者同城的机房网络是非常的高速,并且不会有抖动,网络稳定,可以尝试,理论上是可行,但是一般大家在生产上,可能会跨服务器,或者是跨机房,异地这种的比较少。
N/2 + 1,n 代表的是单主模式里面写节点的数量,为什么 mgr 集群最小的规模是三节点的呢,因为 n 的最小值是 1,如果说低于三个节点的话,primary 节点宕掉之后,选举出新的 primary 节点的时候,不满足 n/2 + 1 这样一个策略,它会产生一个脑裂。

mysql 8.0 mgr 对存储引擎,都用了 mysql 8.0 了,存储引擎当然要用 innodb 存储引擎推荐。都上了 8.0,默认的存储引擎就用 innodb,就不要再用什么 myisam、mem 啦,因为在 mysql 8.0 里面,数据字典的存储引擎都被默认修改成了 innodb 存储引擎,再用别的引擎确实是不太合适的。

如果你想用 mgr 也可以,如果你集群的流量非常大,而且长期处于高负载的状体啊,那我建议你还是不要上 mgr,如果说你长期处在高负载的状态,尤其是高并发的情况,它的这个延迟 primary 和 secondary 之间的延迟非常的大,而且你即使是用了 clone 插件,它会经常性地重搭节点,性能会抖动地很厉害。

Innodb cluster 和 mgr 有什么区别?
A:其实没有什么区别,innodb cluster 和 mgr 不同之处,mgr 在上面搭建一个 myroute,它就成了 innodb cluster,它就这点区别。没有见过用 myroute 的,大家一般都是 mgr 上面自己加个proxy,就是读写分离这样的中间件。有的(公司)是用的自己的,它没有这种探测 primary 节点的机制,它的读写分离的中间件,实现不了故障转移之后,自动把业务重定向到了 primary 节点上面,那么怎么弄,就相当于在中间件和 mgr 中间加了一个 proxy,去实现这样一个目的。

业内数据治理商业平台大部分对于 mysql 支持较深,对 pg 较浅,如何来看这个现象呢?
A:这个很明显,mysql 的用户在国内非常的多,pg 相比起 mysql 来太小众了

Mysql 8.0 对应的 mysql server 一定是 8.0 的,推荐你在生产上尽量升级到 8.0,因为 8.0 偏于稳定,而且它支持 online ddl,不会像 5.7 那样,在 online ddl 的过程中,mysql 挂掉,就把数据文件损坏了,这样的情况,到 8.0 就不存在了。我推荐 5.5、5.6 就不要用了,如果现在还在用,就把它升级到 5.7 或者 8.0。

Mgr 备份怎么做?
A:你原来在 mysql 单实例里面怎么备份,对 mgr 怎么备份就可以了。它和单机没有什么区别,只不过是从一个节点变成了多个 节点组成的一个集群,而且 mysql 内部对于 mgr 在存储引擎层的封装,是非常的良好的,原来单机怎么备份,就怎么备份。在 8.0 里面,可以用 xtrabackup 这样的工具来备份,也可以用 clone 插件去备份

Mgr 做数据迁移,不是只需要迁移到主节点,
即使你迁到了主节点,给集群其他的 secondary 节点,还是会通过一个全量数据同步的方式,还是会从主节点去同步数据,所以你迁移的最好是,先迁移到了单机里面,再激活 mgr 插件,让它通过增量数据的方式来进行数据同步。

线程池,你可以去参考 percona 分支里面 percona server,他们的实现比较好。

使用 mgr 和主从复制的界线,这个就看你的使用场景了,其实能用主从复制的场景,大部分 mgr 也是能用的,只要你并发不是非常的高,而且非常极端的场景下,其实主从复制的场景 mgr 都能够替代。

生产上还有同学敢用 mha,你要是不怕丢数据,就用 mha,我处理过用 mha,生产上丢过数据的,而且这个数据丢得还不少,希望这个事情不要发生在你身上。我建议你现在生产上真的有用 mha 的同学,你赶紧去转 mgr 吧。如果有,可以找一个稍微 C++ 功底好一点的人,看一下 mha 补数据的那一段代码。它那个代码的逻辑,就有很大的问题,丢数据的问题,就出现在那里,能不用 mha 就尽量不用 mha。

你的连接和查询用到的临时表,不在 buffer pool里面,但是如果你的结果集太大,超过内存里面这个临时表设置的阈值,它会生成磁盘临时表。一样的道理,你低发低还好,如果说是高并发的场景下,每个会话都分这么多内存,那么你的内存会被打爆的。