当前位置: 首页 > 科技观察

大型MySQL运维陷阱:使用MyCat踩坑

时间:2023-03-15 14:42:55 科技观察

介绍分布式数据库,已经进入了全面快速发展的阶段,这种发展是与时俱进的,离不开人的需求,因为信息时代的快速发展导致了数据量和交易量的增加。这种现象首先导致了存储瓶颈,因为MySQL数据库本质上是一个单机版的数据库,而只要是单机版,不可避免会遇到的问题之一就是存储问题,因为存储是硬需求,CPU和内存不够用,只是性能差而已,并不能直接否定解决方案或架构。为了解决存储问题,其实我们每个公司或者个人都在努力。解决办法有3个方面:增加磁盘应该是最直接最简单的解决办法,因为磁盘空间不足,当然加磁盘是一个得心应手的办法。比如现在是800G,可以增加到2T。这没问题。如果现在已经达到2T了,当然还是可以增加到5T的盘,但实际上,这个时候DBA可能要捏一把汗了。一个数据量如此庞大的MySQL实例如何运维?如果数据坏了,如何恢复?时间成本呢?5T的数据量已经很恐怖了。估计在业内各大公司,都没有DBA要运维这么大的MySQL实例吧?其实我个人认为,这个量已经不能接受了,最合适的剂量应该保持在1T以下。除此之外,我们必须找到一种方法。当然,这个数据量之所以不适合达到这个规模,可能有人会认为这是性能问题。其实不是,或者说性能问题很小,因为InnoDB使用的是B+树存储方案,最坏情况下不检查小表。数据的时候需要找3层,也就是3页IO,而大表需要4页IO,影响不大。数据压缩为了减少数据占用的磁盘空间,我们通常也会对数据进行压缩,这可以用一条语句来完成,这是InnoDB原生支持的一种方法。一般数据占用会减少到原来的三分之二到二分之一,效果还是够明显的,但是这样处理的数据性能会下降。对于响应要求比较高的业务,可能需要慎重考虑,但这种方式可能还是治标不治本。当数据量不断增长时,过了一段时间,你仍然面临同样的问题。在这种情况下,您不能继续使用此方法来实现它。数据分片数据分片方案目前在业界得到广泛应用。这种方案已经超越了MySQL本身,包括HBase、Redis等,也在使用这种方案。应该说这种方案是扩展性最强的,可以称得上是极致的扩展,而以上两种方案是完全不可扩展的。因此,这种方案成为了业界的主流,这种方案可以称为分布式存储,具体实现也层出不穷。当然,也有优秀的分布式方案,也有一些“伪”的分布式方案。分布式方案需要可扩展性使用分布式,其实最重要的是可扩展性。如果空间不足,可以轻松扩展节点数量,重新平衡数据。这个过程应该不影响业务使用,对业务透明。支持事务分布式数据库。对于业务本身来说,使用上和单机没有太大区别,就是对业务透明。因为MySQL的使用是支持事务的,所以在MySQL改造为分布式之后,事务的特性还是不可或缺的,所以从整体上看,还是有必要支持分布式事务的。SQL语句限制了业务需求的多样性,导致SQL需求种类繁多。对于业务透明,如果某些SQL语句不支持,由此带来的问题是,一方面限制了业务程序的功能和性能,另一方面导致业务程序与“捆绑”的问题分布式数据库”。性能足以使用分布式数据库。其实基本都是对性能要求比较低的业务。即便如此,性能越高,就会有越多的人选择这样的分布式数据库。元数据变化的透明度元数据变化存在于任何数据库中。在单点的情况下,我们有多种友好的方式来实现改表操作,但是在分布式环境下,这种操作可能会变得有问题,因为数据分片导致元数据变化需要多次修改,而且很多问题就出现了,比如原子性、数据可见性、正确性等等,所以这是最基本的问题。底层数据库的高可用意味着经济基础决定上层建筑,在分布式数据库中也是如此。如果底层数据库不稳定,或者数据复制延迟,或者出现数据不一致,上层应用程序的访问精度就会不正确。没有保证,所以底层数据库最基本的就是保证数据的一致性(高可用)。流行的分布式数据库解决方案中间件分库分表(伪分布式)在MySQL的世界里,一个由来已久的话题是:哪个中间件实现的分库分表方案比较好?当然,对于同一个问题,不同的人有不同的理解,都有两个方面。有人说好,有人说不好。我们先来看看这个方案是如何实现的。MyCat的实现架构大致如上图所示。其实如果只看图,这样的架构真的很完美。自动分片、自动聚合、分布均衡都很好的实现了。但事实并非如此。我们可以通过问答的方式一步步理解这个方法的核心问题:MyCat是如何知道数据分片的原理,或者说它是如何确定路由路径的?如何定义或确定一条SQL语句的执行方式,或者说如何决定从哪里取数据,写到哪里?要解决这样的问题,就需要一定的地方来存放它。它的方法是——schema.xml配置文件,连同配置文件一起搞定。那么就会出现很多问题。修改分库分表规则后,如何保证配置和数据同步更新?即使架构。迁移,没办法保证统一,势必会对业务造成影响。如果需要扩容节点,需要做rebalance,怎么办?很多用户基本都是准备一个新的集群,或者手动一点点导出导入数据,导入到目标节点,然后手动修改schema.xml配置文件,然后做一个reload操作,实现了重路由,但是这也会导致上述结果。而这个过程需要处理大量的数据。处理完成后,各种检查需要加倍,占用的空间也需要加倍。这样一来,一个DBA可能只干过一次就有想辞职的冲动。什么是全局表?MyCat支持一个所谓的全局表来解决跨节点数据聚合的问题。实现方式是在每个分片上创建这样一张全局表。它的定义不需要修改。更频繁的表可以定义为全局表。这样,在每个分片节点上,只要使用这张表,就可以实现本地查询、连接等操作,可以解决一些问题,但是问题是如果分片很多(如果是100个分片),如何保证数据的一致性?XA事务对这么多节点有什么影响?如果出现不一致或访问错误,则导致的问题是错误的数据结果。这样的结果肯定不是商家愿意看到的吧?这还不是最重要的,一个数据库集群,为什么要这么特殊的处理一个东西?MyCat到底是做什么的?作为一个中间层,它的工作应该是接收客户端的SQL请求,然后通过语法分析,根据读写原则,确定集群中的一个读写节点,然后等待返回的结果集。对于结果集本身,中间层不需要关心,它只需要将结果集(或异常)原样发送回客户端即可。MyCat的功能远不止于此。语法分析之后,做语义分析得到对应的数据库表结构,同时判断这张表的分发路由规则,然后找到语句中的数据和涉及到的列,进而判断是哪个shardrouteto,如果在分发的时候路由规则配置错误,或者程序计算错误,都会导致整个语句的结果出现不可预知的问题。这部分的前半部分是一个中间层应该做什么?它甚至关心语句中涉及的表结构、主键、数据等信息。这实际上是数据库要做的事情,这些东西能比专业的数据库做得更好吗?我们来看下半场。MyCat接收到结果集后,需要对各个节点进行封装,以便处理一些结果集的聚合计算。结果集(二进制MySQL协议流数据),解析出来,然后根据需要计算(这个计算可能会很慢,也不是全部都可以),计算完成后,打包成MySQL协议流数据并传递给Client,这样一个中间层做了这么多事情,性能如何保证呢?而这些聚合计算OrderBy和GroupBy的处理本身就是数据库自己的事情,但实际上是替数据库做的事情。通过SQL语句的改造实现分布式是不是有点难度?MyCat中间层代表了一种声明分布式数据库的使用方法,但是这种实现方法实际上是在SQL语句上做文章,从客户端拿到的是SQL语句,而给后端数据库的是什么同样是一条SQL语句,只不过这两条SQL语句进行了改造。当然这个方法只能这样,因为后端数据库只接收SQL语句。请问,一个复杂的SQL语句查询操作,通过SQL改造或者改写,可以实现对不同分片数据库的分布式查询吗?想一想,SQL语句虽然通用灵活,但是扩展性或者重写的逻辑还是有点复杂?当然,有人可能会说,我们有底线了,大不了就是把这条语句中的库和表的名字改掉,然后其他的保持不变,分发到各个节点去执行。这没问题,是的,你是对的。如何在同一笔交易中修改不同节点的数据?这个问题就是我们通常所说的分布式事务。到底是怎么回事?MyCat是面向MySQLServer的,也就是说MyCat只能使用SQL语句与MySQLServer通信,仅限于MySQLSQL语句的功能。有多少人在分布式实现中使用MySQLXA本身?如果MyCat实现跨节点数据更新,则不需要MySQLXA。还能用什么?没有别的选择,靠一个本身没有多少人用,可能会出现很多问题,包括性能,bug函数,那么如何保证上层MyCat乃至应用的可靠性呢?当然,基于这些问题,一些解决方案选择不使用XA。如果某些节点出现故障,则选择忽略它们而不解决它们。MyCat后端数据库的架构是怎样的,如何保证稳定性、可靠性和高可用?根据一些文章,之前可以选择master-slavereplication,现在可以选择GaleraCluster,也可以选择updatedMGR。当然,不得不说,从前到后,确实可以保证更好的可靠性,但是有一个很大的问题,就是Galera的门槛比较高。如果有问题,很少有人能解决(我很自豪Qunar可以被称为世界上为数不多的使用Galera更多更好的公司之一),然后MGR本身必须等待,并且需要很长一段时间使用它。这个问题还是要回到主从复制上来,这是个老问题。主从复制的一致性很难保证。如果MyCat使用读写分离策略将读发给slave,而这恰好是延迟的,这样的结果可能是整个应用程序的计算结果是错误的。当然,也可以说是有延迟检查。问题是,如果使用延迟检查,是否还有其他参数可以配置?如果延迟超过100秒,查看主库?是的,但不是延迟100秒吗?那么就可以设置为0,当你看到0的时候,你以为真的是0吗?其实就是主从复制的劣势。所以问题还是回到了起点。经济基础决定上层建筑。基础不好,上层怎么办?当分片过多时,性能如何保证损失最小?不知道MyCat有没有做过这个问题。优化,比如10个分片,如果一条语句的执行涉及这十个分片,那么在每个分片上重写语句后,对应的语句必须分别在这十个分片上执行。是串行还是并行?如果是串行的话,性能必然会下降10倍以上,所以如果做得好一点,那就是并行的,但是并行的实现方式是在MyCat连接上创建10个线程来处理这十个节点的实现,如果这样的连接太多,MyCat对系统的影响会非常大,性能还是不好。当然,也可以说在这里做一个连接池,是的,是可以的,但是MyCat是这样做的吗?性能怎么样?如果超时,则整个访问将失败。如果配置文件或者配置库出现问题,那么整个集群会怎么样呢?前面提到MyCat使用schema.xml来配置分库分表策略。这是一个配置文件。MyCat本身是高可用的。如果有多个集合,如何解决它们的同步问题?如果没有同步(或者同步有问题,或者延迟等),某个MyCat挂了,当业务切换到另一个MyCat时,此时的情况就是失败……过错……。因为数据乱了。可能造成的问题是写错了位置,会导致整个集群的数据写的不好。感觉比直接删除还严重。同样的问题,我感觉MyCat可能会优化这一点,可能会改为存储在某个数据库中,这样集中管理就不需要同步了。想法是好的,但是这就相当于把鸡蛋放在一个篮子里,如果这个配置库出了问题,业务会跑到哪里去?如何进行DDL?这个问题可能是每个人都关心的事情。MyCat把数据分成不相关的MySQL节点的分片,那么在一个单一的很多表的修改策略就不能再用了,DDL是必须要保证每个节点同时完成的东西。分布式端如何保证?据我研究,好像现在用MyCat的人,都是通过“在每个节点上同时开始更新表结构”的方式来完成的。当然,你必须选择午夜。当然个人觉得也是可行的,因为毕竟用过,没有更好的。解决这个问题的方法。当然,让我们谈谈后果。如果不能做到无缝原子修改,对业务的影响不小,可能会出现很多SQL报表不存在的问题。如果一条语句的修改完成时间与另一条语句相差较大,则两者相减的时间就是失败时间。根据我的研究,MyCat也实现了自动故障转移的功能。这个可靠吗?我们现在讨论的是分布式架构方案,这个问题是关于某个MyCat发现后端数据库无法连接的问题,自动切换的功能,这个很明显,我们要的是分布式,一个“一个”MyCat节点想的问题真的是他想的吗?也就是说,一个节点不能保证他判断的或者他看到的现象是真实的,那么这种情况就存在错误切换的情况,如果其他中间节点不知道这种情况,或者没有收到切换消息时间一长,就会出现多点写作题,很吓人。这不是自相矛盾吗?我们想要的是分布式的,结果就出现了“任意”链接,可靠性下降了很多。关于分布式监控切换的问题,因为去哪儿用的mysql-sentinel监控GaleraCluster,这一点让我感触很深,所以这里不得不说一下。如何在MyCat上进行备份?是否可以恢复快照?说到备份,作为数据库用户,应该没有人不清楚,也没有人会认为它不重要吧?当然,重要是重要,但是这种事情是重要又不紧急的工作,但是没有它是不行的。这连公司内审都过不了。也许我们都不想使用他。言归正传,说到这么重要的备份工作,MyCat上的情况如何呢?了解一些基本原理的人可能会比较清楚,Xtrabackup、mysqldump等也都有,但是备份完之后,可能还是觉得没思路,因为这样的工具只能备份一个MySQL节点。如果分成10个分片(10个MySQL节点),备份10次就可以完成,但是需要注意的是,备份10次生成的是10个备份集,而不是1个备份集。这十个备份集完全无关紧要。此时,我可能会问一个更极端的问题:如果有一天(当然我们都希望有这么一天)整个机房都挂了。当然,如果你“运气好”,有备份,那么在这种情况下,如何恢复一个可用数据一致且完整的集群快照呢?这时候,有些人可能会很快,将十个备份集全部恢复,然后开始。但问题是这十个是无关紧要的,备份时间并不是同时完成的。同表的十个碎片,有的***数据在8点,有的在9点,有的甚至是昨天的。这样恢复的表还能用吗?基于这样一张表的查询结果靠谱吗?可想而知。当然,有人可能会说,我们的数据不需要一致性快照,甚至更多,我们只需要备份元数据路由表或者配置文件,那么这个没问题,如果MyCat只是定位于存储Zabbix监控数据,还是日志数据,能丢掉不必要的数据,没有价值的数据,那我觉得没什么问题。也有人会说我们机房不会挂,或者我们的存储本来就是跨机房的。如果宕机,可以直接切换到另一个机房。那么这个时候还有一个问题。如果切换Delay时有副本,丢失了一部分数据,那么整个集群就会出问题,因为只要一个分片的数据出现问题,整个集群就会出问题。或者另一个问题,假设你的机房真的不会挂,但是我们经常会遇到这样的需求,如果我想找回前几天某个时间的数据,那我还需要备份恢复一个快照此时。还有什么好说的,告诉我怎么做?可能有人会有疑惑,他会说我们是逻辑备份,这样备份就是整个库或者表的一致快照,这不就解决了有问题吗?我同意这位同学的观点。能够彻底解决一致性问题是绝对没错的,但是熟悉MySQL的人都知道,像mysqldump这样的逻辑备份工具,到底有多慢呢?现在使用分布式存储,数据量肯定非常大。这个时候还用这样的逻辑备份?你想让我做什么?即使备份完成了,你试过恢复逻辑数据吗??恢复几千兆字节的数据需要多长时间?你计算过吗?想想就头疼。一条不归路。..如果您已经在使用MyCat,发现它的风险太大,我该如何下载呢?这个问题很好,说明你作为数据拥有者已经在思考如何保证数据的可靠性,规避风险问题是MyCat确实有风险,但是如果你已经登上了“贼船”,想要下车,这时候我可能想问(诸葛亮做了一件事之后),你为什么不多想想这个结构呢?公司的数据就是金钱。思来想去,可上可下,可来可回。它会增值吗?如果数据搞砸了,这时候没人赔你。不如上云。不过既然上传了,那我们就来说说如何下载吧。目前感觉最靠谱最安全的方法好像只有一个,步骤如下:先停止业务,停止所有写业务(不需要找深夜时间,因为12小时根本无法完成)。通过上面提到的mysqldump进行逻辑备份,导出所有库,生成.sql文件。然后找一个靠谱的MySQL架构(真正的分布式数据库,或者磁盘足够大的话,可以不用分布式,但是可以用ShareNothing的方案。也许你需要的不是分布式,但你只是被愚弄)。.sql文件被导入其中。然后将读业务迁移到新的数据库架构中。将写业务迁移到新的数据库架构上,然后启动它们。这时候应该可以提供正常的数据库服务了。我们可以关注这个过程。从第1步到第5步需要多少时间?当然,这是一个艰难的时期。有必要移动数据。逻辑备份和恢复太慢了。我觉得时间的单位可以用天来表示。算了。这时候负责人就可以想想我用MyCat干什么了。商务免签卡停用了好几天,就是为了弥补当年的一个错误决定,后悔莫及。当然,有些人可能有其他的解决方案,但是由于每个分片都是相互独立的,所以在不停止业务的情况下,仍然存在上述“一致性快照”的问题。***我想说的是,大家一定要对公司的数据保持谨慎,时刻保持负责任的态度。折腾数据真的无法升值。MyCat的配置复杂吗?上手容易吗?我们只需要看一张图。你能想象这是它的配置文件吗?看完之后,估计你没有使用的欲望了。很多人用过之后这样评价:配置文件如下:原来是一个XML文件。这位产品经理当时是怎么想的?有没有想过以后再优化一下?***一个问题,分库分表用什么好?还有什么?没有,这是一条不归路。因为说白了就是伪分布式方案,基础不好,上层做不好,所以一直在补各种坑,很累很累。现在你可以回过头来想一想,为什么一些非常强大和知名的公司做的中间件产品不做这些事情,比如ProxySQL、Maxscale、MySQLRouter等,为什么?他们的技术不好吗?或者没有这样的需求?我仍然认为有需求。人和企业的需求是一样的,但解决方案可能不同。他们可能早就认为这是一条错误的路,所以你不会选择走,但对于像MyCat这样的解决方案,你可能要回顾一下,思考前进的方向。互联网处理大规模在线访问数据的方式的解耦普遍存在于互联网技术栈的方方面面。你为什么这么做?我想是因为大家不想拖延,不想牵一发而动全身。在MySQL数据库层面,用了一个重量级的中间层之后,你会发现统一看起来很好,但是这样一拉可能会牵一发而动全身,其实并不是什么好事。MySQL等数据库在互联网领域兴起并被大规模使用,在账户、订单、计费等关键业务中使用的也不在少数。在大型互联网公司中,MySQL的使用必须分为数据库和表。通过各种纵横切分,可以将一个数据库变成一堆数据库,这就是所谓的数据库集群。但是,很少看到在使用MySQL的时候,会在上面架设一个重量级的所谓分布式中间层,导致紧耦合,这与互联网高效联运是背道而驰的。互联网数据库集群应该是物理上离散的,每个实例都可以自由控制和迁移,也就是所谓的解耦。解耦的好处是可以让你自由处理各个独立的实例或者集群,方便根据实际情况处理业务带来的变量,升级的升级,收缩的收缩,对于每个业务或者每个业务的数据库定义不同的维护级别,灵活掌握,随机变化。解耦的好处是可以提高数据库的绝对性能。数据从业务到磁盘,或从磁盘到业务的路径越短,其效率就越高。很多使用MySQL的方式都是使用一个简单的中间层来分发SQL。这种中间层功能明确,结构简单,灵活高效,一般不会损失太多性能。这就好比MySQL出品的MySQLRouter,MariaDB出品的Maxscale。Percona的ProxySQL,国内流行的极数云舟的Arkproxy,都为选择使用中间层实现数据结构指明了一个方向。解耦的好处是让你的数据库只做数据库最擅长的事情。它可以保证你数据的安全存储,它可以保证你数据的高效访问,它可以保证你的数据被并发处理,它可以保证你数据的灵活访问,这还不够吗?综上所述,我们再次相信一个道理,MySQL简单高效,因为效率高而流行。当然,如果你不想在业务层做分库分表来适配MySQL数据库架构,而是想通过对业务透明的分布式数据库来提供业务服务,我推荐一个真正的分布式数据库解决方案,能够解决的是强大的存储扩展能力、分布式计算、对业务读写透明、友好的故障转移。这是他们的优势,也是他们的初衷。真正意义上的分布式解决方案真正的分布式解决方案,其实不用说太多,满足上述需求即可。并且目前也有比较成熟的解决方案,比较有代表性的产品有Google的Spanner&F1,还有国内的数据库SequoiaDB,TiDB等。关于巨杉数据库,我之前写过一篇文章,有兴趣的同学可以看看《【原创首发】兼容MySQL的开源分布式数据库SequoiaDB在去哪儿网的实践》对比一下,这种分布式数据库对业务无侵入,MySQL数据实现了云存储的特性,100%兼容MySQL,可扩展性非常好,天然支持分布式事务,数据节点和路由节点的延迟非常小,并采用一致性算法保证数据的强一致性。这一切都建立在一个正确的基础之上,高楼大厦势必将基于MyCat的伪分布式数据库解决方案推向无人问津的深渊,直至被淘汰、消亡。综上所述,使用MyCat的用户还是蛮多的。现在了解了行业市??场,更能理解他们,因为有需求,但真的没有解决方案。选择使用它,其实是无奈之举。毕竟他是开源的,我也没什么怨言,因为是免费的,那用它有什么意义呢?我也推荐大家去尝试一下。只有当你知道痛苦时,你才会感受到新解决方案的美丽。.这篇文章讲的关于MyCat的一系列问题主要是为了让业内的同学不要继续挖坑,所以做了一些总结。所描述的内容仅限于我目前对MyCat的理解和了解。如有错误或不足之处,欢迎私信指正或补充,谢谢。

猜你喜欢