面试官:看你简历有写精通 MySQL 读写分离,那咱们聊聊吧 | 百战百胜 – https://www.besthub.tech/

29次阅读

共计 3069 个字符,预计需要花费 8 分钟才能阅读完成。

面试题

  • 你有没有做 MySQL 读写分离?
  • 如何实现 MySQL 的读写分离?
  • MySQL 主从复制原理的是啥?
  • 如何解决 MySQL 主从同步的延时问题?

面试官心理分析

高并发场景下,系统需要处理大量的用户请求,这些请求可能包括数据的读取和写入。在数据库层面,如果所有的读写请求都直接作用在同一个数据库实例上,那么很容易因为单个实例的处理能力有限而成为瓶颈,导致系统性能下降。

读写分离是一种常用的数据库架构优化手段,它的核心思想是将数据库的读操作和写操作分离到不同的数据库实例上。这样可以充分利用多个数据库实例的处理能力,提高系统的并发处理能力。

在实际应用中,当系统接收到一个写请求时,它会直接发送到主库进行处理;而当系统接收到一个读请求时,它会根据一定的策略(如负载均衡算法)选择一个从库进行处理。这样,就可以有效地分散读写请求,提高系统的并发处理能力。

需要注意的是,读写分离虽然可以提高系统的并发处理能力,但也带来了一些挑战和复杂性,比如数据同步的延迟、从库的数据一致性问题、故障恢复等。因此,在实施读写分离时,需要综合考虑这些因素,制定合理的策略和方案。

题目剖析

如何实现 MySQL 的读写分离?

基于主从复制架构的读写分离是一个常见且有效的策略来应对高并发场景。简单来说,这个策略的核心是设置一个主数据库(或称为“主库”)和多个从数据库(或称为“从库”)。

  1. 主库(Master):这是负责处理所有写操作(如 INSERT、UPDATE、DELETE)的数据库。当应用程序需要进行数据修改时,它会与主库进行交互。
  2. 从库(Slave):这些数据库是主库的副本,用于处理读操作。从库会定期从主库那里复制数据,确保自己与主库保持同步。当应用程序需要读取数据时,它会与一个或多个从库进行交互。

MySQL 主从复制原理的是啥?

在 MySQL 的主从复制架构中,读写分离的实现过程如下:

  1. 主库(Master):

    • 主库执行所有的写操作(如 INSERT、UPDATE、DELETE 等),并将这些变更写入其二进制日志(binlog)。binlog 记录了所有修改数据库数据的 SQL 语句。
    • 当有从库连接到主库时,主库会将其 binlog 的位置和文件名发送给从库。
  2. 从库(Slave):

    • 从库连接到主库后,会启动一个 IO 线程。
    • 这个 IO 线程负责从主库上读取 binlog,并将其写入从库本地的中继日志(relay log)。中继日志是主库 binlog 的副本,但它保存在从库上。
    • 同时,从库还会启动一个 SQL 线程。
    • SQL 线程从中继日志中读取事件(即 binlog 中的变更),并在从库上重新执行这些 SQL 语句。
    • 通过这种方式,从库的数据会被更新,以匹配主库的数据。

这个过程确保了从库的数据与主库保持一致。当主库执行写操作时,这些操作会被记录在 binlog 中,并通过主从复制过程传播到从库。从库通过执行这些操作来保持与主库的数据同步。

虽然从库的数据与主库保持一致,但从库通常是用于读操作的,而写操作仍然在主库上进行。这样,读写分离架构可以有效地分散读写请求,提高系统的并发处理能力。
面试官:看你简历有写精通 MySQL 读写分离,那咱们聊聊吧 | 百战百胜 - https://www.besthub.tech/

从库同步主库数据的过程涉及到一些关键的问题和挑战。从库串行执行主库上的操作意味着存在数据同步的延迟,这在高并发场景下尤为明显。这种延迟可能导致刚写入主库的数据在从库上无法立即读取,需要等待一段时间。

此外,如果主库突然宕机,并且数据尚未完全同步到从库,那么从库上可能会缺失部分数据,这增加了数据丢失的风险。为了解决这些问题,MySQL 引入了两种机制:半同步复制和并行复制。

半同步复制(Semi-Synchronous Replication):这种复制模式通过强制主库在写入 binlog 日志后,立即将数据同步到至少一个从库。从库将日志写入本地的 relay log 后,会向主库发送一个确认信号(ack)。只有当主库接收到至少一个从库的确认信号后,才认为写操作完成。这种方式可以降低数据丢失的风险,因为即使主库宕机,从库也至少拥有最近一次同步的数据。

并行复制(Parallel Replication):为了减少从库同步的延迟,MySQL 引入了并行复制。在这种模式下,从库会开启多个线程,并行读取 relay log 中不同数据库的日志,并并行重放这些日志。这样,从库可以同时处理多个数据库的数据同步,提高了同步的效率和速度。

这两种机制共同增强了主从复制架构的可靠性和性能,使得在从库上读取数据时,既能保证数据的完整性,又能减少同步的延迟。然而,这些机制也需要根据具体的业务场景和需求进行适当配置和调优,以达到最佳的性能和数据一致性。

如何解决 MySQL 主从同步的延时问题?

场景描述

假设有一个在线服务,其中包含一个数据库操作逻辑,该逻辑首先向数据库插入一条新数据,然后立即查询这条数据,并基于查询到的结果更新这条数据的某些字段。这个操作逻辑看似简单,但在高并发场景下,特别是当使用了主从复制架构时,就可能会遇到问题。

问题出现

当系统的写并发量达到很高的水平,比如你提到的 2000 次 / 秒时,主库上的写操作会非常频繁。由于主从复制是串行的,从库同步主库数据的速度可能会跟不上主库的写速度,导致从库上的数据相对于主库有一定的延迟。这个延迟可能只有几十毫秒,但在高并发场景下,这足以导致一些问题。

具体来说,当某个写请求在主库上成功插入一条数据后,紧接着的读请求可能会去从库上查询这条数据。由于从库上的数据还没同步过来,这个读请求可能会返回一个空结果或者是一个旧的结果。基于这个错误的结果,接下来的更新操作可能就不会执行,或者执行了错误的更新。

影响

这种由于主从同步延迟导致的数据不一致问题,可能会导致线上出现一些难以追踪的 bug。就像你所描述的,每天总有一些期望被更新的重要数据在高峰期没有被正确更新,这可能会影响到用户的体验和服务的质量。用户可能会向客服反馈问题,而客服在调查后可能会将问题反馈给开发团队。

解决方案

首先我们通过 MySQL 命令:

show slave status

查看 Seconds_Behind_Master,可以看到从库复制主库的数据落后了几 ms。

采取的策略如下:

  • 分库(Sharding):将单一的高并发主库拆分为多个主库,每个主库负责一部分数据的写入。这样,每个主库的写并发就减少了几倍,从而减轻了单个主库的压力。当每个主库的写并发降低后,主从延迟问题可能变得不再显著。
  • 并行复制(Parallel Replication):MySQL 支持并行复制,这意味着从库可以并行地应用多个数据库的 binlog 事件。这有助于提高从库同步主库数据的速度,特别是在有多个独立数据库的情况下。但是,如果单库的写并发达到了非常高的水平,即使打开了并行复制,从库仍然可能无法及时同步主库的数据。
  • 代码逻辑调整 :开发者在编写代码时应该意识到主从延迟的存在,并避免在插入数据后立即从从库查询数据。如果确实存在这种需求,即需要先插入数据,然后立即查询到最新数据,再执行其他操作,那么应该考虑使用其他策略来处理。
  • 直连主库查询 :对于某些特定的查询需求,如果确实需要立即获取到最新写入的数据,可以考虑让这部分查询直接连接到主库进行查询。然而,这种做法会破坏读写分离的架构,增加主库的负载,并且可能引发其他一致性问题。因此,这种方法应该谨慎使用,并且只适用于那些确实无法避免立即查询最新数据的场景。

综上所述,解决主从延迟问题需要根据具体的业务场景和系统负载情况来制定合适的策略。分库、并行复制、代码逻辑调整和直连主库查询都是可能的解决方案,但每种方案都有其优缺点,需要根据实际情况进行权衡和选择。

正文完
 0