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

读多写少之时,MySQL如何进行优化为好

时间:2023-03-19 20:54:23 科技观察

如何在读多写少的情况下优化MySQL?案例背景案例分析MySQL主从结构案例答案总结巨大的流量来了。如果你是订单系统的技术负责人,你如何应对突发的读写流量?这是一个非常典型的应用场景。我想很多研发工程师都会回答:使用Redis作为MySQL的缓存,然后在用户查看“订单中心”的时候查询订单缓存,帮助MySQL抵御大部分的查询请求。应用缓存的原则之一就是保证缓存命中率足够高,否则很多请求会穿透缓存,最终命中数据库。但是在“订单中心”这样的场景下,每个用户的订单都是不一样的。除非将数据库订单信息全部缓存起来(这会给架构带来复杂性),否则缓存的命中率还是很低的。所以在这种场景下,缓存只能作为数据库的一种前置保护机制,但是还是会有大量的流量冲击数据库,而且随着用户订单的不断增加,读写流量也会越来越多请求到MySQL,当单个MySQL无法支持大量并发请求时,怎么办?案例分析互联网上大部分系统的访问流量都是读多写少,读写请求的差距可能达到几个数量级,就像你在京东上的商品浏览量是肯定的远远大于您的订单量。因此,你不得不考虑优化数据库以抵抗高查询请求。首先要做的是区分读写流量区域,方便读流量单独扩展。这个过程就是流量的“读写分离”。读写分离是提高MySQL并发度的首选方案,因为当单个MySQL无法满足需求时,只能使用多个具有相同数据的MySQL实例组成的集群来承担大量的读写请求。MySQL主从结构MySQL实现读写分离的前提是将MySQL集群拆分成“主+从”结构的数据集群,从而在程序中实现读写分离,数据MySQL集群的主库和从库同步是通过主从复制实现的。那么面试官就会问你“MySQL集群是如何实现主从复制的?”另一个问题是“当你向MySQL集群提交事务时,MySQL执行了哪些操作?”面试官往往会从这个问题点入手,挖掘你对MySQL集群主从复制原理的理解,然后模拟一个业务场景,让你给出主从复制问题的架构设计方案。所以,对于面试官的套路,需要做好以下准备:掌握读多写少场景下的架构设计思路,知道缓存不能解决所有问题。“读写分离”是提高系统并发能力的重要手段。深入理解数据库主从复制,掌握其原理、问题及解决方法。从实践出发,做到技术的认知抽象,从方法论的角度看设计。案例解答MySQL主从复制的原理无论是“MySQL集群是如何实现主从复制的”还是“当你向MySQL集群提交事务时,MySQL集群执行哪些操作?”面试官主要问你:MySQL主从复制的过程是怎样的?一般来说,MySQL的主从复制依赖于binlog,它记录了MySQL上的所有变化,并以二进制的形式保存在磁盘上。复制的过程就是将binlog中的数据从主库传输到从库。这个过程一般是异步的,即在主库上执行事务操作的线程不会等待复制binlog的线程同步完成。为了方便大家记忆,我把MySQL集群的主从复制过程梳理成3个阶段。WritetoBinlog:主库写入binlog日志,提交事务,更新本地存储数据。同步Binlog:将binlog复制到所有从库,每个从库将binlog写入临时日志。回放Binlog:回放binlog,更新存储的数据。但是在面试的时候不能简单的讲这几个阶段,而是要尽可能详细的解释主库和从库的数据同步过程,让面试官感受到你技术的扎实(详细的过程如下)。MySQL主库收到客户端提交事务的请求后,首先写入binlog,然后提交事务,更新存储引擎中的数据。交易提交后,会向客户端返回“操作成功”的响应。从库会创建一个专用的I/O线程连接到主库的logdump线程接收主库的binlog日志,然后将binlog信息写入relaylog的relaylog,然后返回主库“复制成功”的响应。从库会创建一个重放binlog的线程来读取中继日志,然后重放binlog更新存储引擎中的数据,最终实现主从之间的数据一致性。完成主从复制后,写数据时只能写主库,读数据时只能读从库,这样即使写请求会锁表或锁记录,也不影响读取请求的执行。同时,当读流量比较大的时候,可以部署多个从库来分担读流量。这就是“一主多从”的部署方式。在垂直电商项目中可以使用这种方式来抵抗高并发读流量。.此外,从库还可以作为备库使用,避免主库故障导致数据丢失。MySQL一主多从当然,一旦你提到“一主多从”,面试官很容易设下一个圈套问你:大促期间流量大的时候,是否可以抗大多加几个从库来提升?并发读取请求?当然不是。因为从库数量的增加,连接到从库的I/O线程也变多了。主库也需要创建相同数量的日志转储线程来处理复制请求。主库的资源消耗比较高,也受主库的限制。图书馆的网络带宽。因此,在实际使用中,一个主库后面一般会有2到3个从库(1套库,1个master,2个slave,1个backupmaster)。这是一主多从的MySQL集群结构。其实从MySQL主从复制过程也可以发现,MySQL默认是异步模式:MySQL主库提交事务的线程不会等待binlog同步到各个从库,然后返回客户端结果。在这种模式下,一旦主库宕机,数据就会丢失。这时候面试官一般会问你“MySQL主从复制还有哪些模型?”主要有三种类型。同步复制:事务线程等待所有从库副本的成功响应。异步复制:事务线程根本不等待库的复制成功响应。半同步复制:MySQL5.7之后新增的一种复制方式。两者之间,事务线程不需要等待所有的replica都响应成功,只要有一部分replica响应成功即可,比如一主两从的集群。只要数据成功复制到任意一个从库,主库的事务线程就可以返回给客户端。这种半同步复制方式兼顾了异步复制和同步复制的优点。即使主库宕机,至少有一个从库有最新的数据,不存在数据丢失的风险。说到这里,你已经基本掌握了MySQL主从复制的原理,但是如果面试官想挖掘你的架构设计能力,他还会从架构设计上考察你是如何解决MySQL主从复制延迟问题的,比如问你“在系统设计中有哪些解决方案可以解决主从复制的延迟问题?”从架构上解决主从复制延迟我们结合实际案例设计一个主从复制延迟的解决方案。在电商平台上,用户每次发表商品评论,都会先调用评论review,目的是对用户发表的商品评论进行言论监听、图片色情等操作。更新评论主库后,商品发布模块会异步调用评论模块,并将评论ID传递给评论模块,评论评论模块再通过评论ID查询从库中获取完整的评论信息.这时候如果主从数据库出现了延迟,就无法从从数据库中获取到评论信息,整个过程就会出现异常。主从延迟影响评论阅读的实时性。这是主从复制延迟导致的查询异常。有很多解决方案。我将为您提供几种解决方案。使用数据冗余,不仅可以发送产品ID,还可以在异步调用审计模块时发送审计模块需要的所有评论信息,避免重新从库中查询数据(此方案简单易实现,建议您选择)。但是要注意每次调用的参数大小,太大的消息会占用网络带宽和通信时间。使用缓存方案可以在写入主数据库的同时将评论数据写入Redis缓存,这样其他线程在获取评论信息时会先查询缓存,也可以保证数据的一致性。但是这种方式会带来缓存和数据库的一致性问题。比如两个线程同时更新数据。操作步骤如下:线程A先更新数据库为100,然后线程B更新数据库和缓存中的数据为200,然后线程A更新缓存为100,所以数据库中的值200为与缓存中的值100不一致。一般情况下,在使用缓存解决MySQL主从复制延迟的时候,会出现数据库和缓存数据不一致的情况。使用此解决方案直接查询主数据库时必须谨慎。一定要事先明确,查询的数据量不大。否则主库的写请求会锁行,影响读请求的执行,最终对主库造成比较大的压力。当然,除了从架构的角度考察你对MySQL主从复制延迟的理解,面试官还会问你一些扩展性的问题,比如:当MySQL分离主从时,数据库的使用方式发生了变化.本来只需要用一个数据库地址就可以操作数据库,但是现在需要用一个主库地址和多个从库地址,而且需要区分写操作和查询操作。如何从工程代码设计上实现主从库?数据访问呢?实现主从库数据库访问的一个简单的方法是在项目中预先配置好所有的数据源,每个数据源对应一个主库或者从库,然后修改代码,在代码逻辑中make判断并将SQL语句发送到指定的数据源进行处理。该方案简单易行,但SQL路由规则侵入代码逻辑,不利于复杂项目的代码维护。另一种方法是:独立部署的代理中间件,如MyCat,部署在独立的服务器上,一般使用标准的MySQL通信协议,可以代理多个数据库。该方案的优点是隔离了底层数据库和上层应用的访问复杂性,更适合有独立运维团队的公司选型;缺点是所有的SQL语句都要经过两次网络传输,有一定的性能损失,然后运维中间件是一个专业复杂的工作,需要一定的技术沉淀。综上所述,我们先从一个案例来理解,当互联网流量读多写少的时候,需要通过“读写分离”来提升系统的并发能力,而因为“读写分离”的前提》就是要成为“主+从”的数据集群架构,所以我们讲了主从复制的原理,以及如何解决主从复制带来的延迟。