113. MySQL 主从复制的过程是怎么样?#

分析
主从复制过程梳理成 3 个阶段:
- 写入
binlog:主库写binlog日志,提交事务,并更新本地存储数据; - 同步
binlog:把binlog复制到所有从库上,每个从库把binlog写到暂存日志中; - 回放
binlog:回放binlog,并更新存储引擎中的数据。
回答
主从复制主要有 3 个阶段:
- 主库修改数据后,会写入
binlog日志。从库连接到主库之后,主库会创建一个log dump线程,用于发送binlog的内容; - 从库会创建一个专门的 I/O 线程来连接主库的
log dump线程,接收主库的binlog日志,再把binlog写入relay log(中继日志)里,再返回给主库“复制成功”的响应; - 接着从库还会创建一个用于回放
binlog的 SQL 线程,去读relay log,回放binlog更新存储引擎中的数据,最终实现主从的数据一致性。
114. MySQL 提供了几种复制模式?默认的复制模式是什么?#
分析
说出 3 种同步模式:同步复制、半同步复制、异步复制,然后说一下各个模式的适合场景。
回答
主要有三种:同步复制、半同步复制、异步复制,MySQL 默认的复制模式是异步复制。
- 同步复制:MySQL 主库提交事务的线程要等待所有从库的复制成功响应,才返回客户端结果。这种方式是性能最差的复制模式,但是能保证数据的安全性,如果对数据安全性比较高的业务,可以考虑采用同步复制的模式;
- 异步复制:MySQL 主库提交事务的线程并不会等待
binlog同步到各从库,就返回客户端结果,这种模式性能是最高的,但是一旦主库宕机,数据就会发生丢失; - 半同步复制:介于两者之间,事务线程不用等待所有的从库复制成功响应,只要一部分复制成功响应回来就行,比如一主二从的集群,只要数据成功复制到任意一个从库上,主库的事务线程就可以返回给客户端。这种半同步复制的方式,兼顾了异步复制和同步复制的优点,即使出现主库宕机,至少还有一个从库有最新的数据,不存在数据丢失的风险。
115. MySQL 主从复制的数据延迟怎么解决?#
分析
考察解决主从复制延迟问题的方案设计。
回答
- 使用缓存解决:可以在写入数据主库的同时,把数据写到 Redis 缓存里,这样其他线程再获取数据时会优先查询缓存,也可以保证数据的一致性。不过这种方式会带来缓存和数据库的一致性问题;
- 直接查询主库:对于数据延迟敏感的业务,可以强制读主库。但是我们要提前明确查询的数据量不大,不然会出现主库写请求锁行,影响读请求的执行,最终对主库造成比较大的压力。
116. MySQL 主从架构中,读写分离怎么实现?#
分析
- 一种简单的做法是:提前把所有数据源配置在工程中,每个数据源对应一个主库或者从库,然后改造代码,在代码逻辑中进行判断,将 SQL 语句发送给某一个指定的数据源来处理。这个方案简单易实现,但 SQL 路由规则侵入代码逻辑,在复杂的工程中不利于代码的维护;
- 另一个做法是:独立部署的代理中间件,如 MyCat,这一类中间件部署在独立的服务器上,一般使用标准的 MySQL 通信协议,可以代理多个数据库。该方案的优点是隔离底层数据库与上层应用的访问复杂度,比较适合有独立运维团队的公司选型;缺陷是所有的 SQL 语句都要跨两次网络传输,有一定的性能损耗,再就是运维中间件是一个专业且复杂的工作,需要一定的技术沉淀。
回答
可以独立部署的代理中间件 MyCat 来实现读写分离。
117. MySQL 主库挂了怎么办?#
分析
MySQL 没有像 Redis 集群有哨兵模式,可以自动将从库升级为主库。
MySQL 的“发现主服务器宕机”“处理故障转移”逻辑要由数据库高可用套件完成,常用的是 MHA,它是一款开源的 MySQL 高可用程序,它由两大组件所组成:MHA Manager 和 MHA Node。
- MHA Manager 通常部署在一台服务器上,用来判断多个 MySQL 高可用组是否可用。当发现有主服务器发生宕机,就发起 failover 操作。MHA Manager 可以看作是 failover 的总控服务器;
- 而 MHA Node 部署在每台 MySQL 服务器上,MHA Manager 通过执行 Node 节点的脚本完成 failover 切换操作。
MySQL 的高可用套件用于负责数据库的 Failover 操作,也就是当数据库发生宕机时,MySQL 可以剔除原有主机,选出新的主机,然后对外提供服务,保证业务的连续性。
回答
MySQL 主从复制没有实现发现主服务器宕机和处理故障迁移的功能,要实现自动主从故障迁移的话,我简单了解过,可以使用开源的 MySQL 高可用套件 MHA,MHA 可以在主数据库发生宕机时,剔除原有主机,选出新的主机,然后对外提供服务,保证业务的连续性。
118. 什么是分库分表?什么时候需要分表?什么时候需要分库?#
分析
分库分表使用的场景不一样:
- 分表是因为数据量比较大,导致事务执行缓慢;
- 分库是因为单库的性能无法满足要求。
回答
分库分表的意思是把原本存储于单个数据库上的数据拆分到多个数据库,把原来存储在单张数据表的数据拆分到多张数据表中,实现数据切分。
分库分表使用的场景不一样:
- 当单张数据表的数据量太大的时候,经验值是 500W 以上的数据量,就会影响了事务的执行效率,这时候就要考虑分表了,通过减少每次查询数据总量来解决数据查询缓慢的问题;
- 当单台 MySQL 扛不住高并发流量的时候,就要考虑分库了,把并发请求分散到多台 MySQL 实例中。
119. 分库分表后,会产生什么问题?怎么解决?#
分析
- 分布式事务问题,解决方式:
2PC两阶段、3PC三阶段提交协议(强一致性,性能差,用的少);TCC分段提交、基于本地消息表来实现分布式事务(最终一致性,性能较好,用的多);
- 全局 ID 唯一性问题,解决方式:
- 雪花算法生成 ID、或者美团 Leaf 算法生成唯一主键 ID;
- 跨库跨表关联查询问题,解决方式:
- 冗余额外字段避免跨库关联,或者交给数据库分库分表中间件来实现;
- 将数据全量存储到 ES 中去,通过 ES 进行查询(如果简历上写用过 ES,可能会问 MySQL 的数据是怎么同步到 ES 的);
- 跨库跨表的排序问题,解决方式:
- 业务代码或者数据库分库分表中间件分别查询每个子表中的数据,然后汇总进行排序;
- 将数据全量存储到 ES 中去,通过 ES 进行查询(同上);
- 跨库跨表
COUNT查询的问题,解决方式:- 将计数的数据单独存储在一张表里;
- 将聚合查询的数据同步到 ES 中,交给 ES 进行查询(同上)。
回答
- 分布式事务问题:对业务进行分库之后,同一个操作会分散到多个数据库中,涉及跨库执行 SQL 语句,也就出现了分布式事务问题。解决方式:如果对一致性要求比较高的业务,比如金融类的业务,可以使用分布式事务中间件,实现
TCC事务模型;互联网的业务通常对一致性要求低,会使用基于本地消息表来实现分布式事务,达到最终一致性的效果,这个分布式事务的方案性能会好一些; - 全局 ID 唯一性问题:在单库单表时,业务 ID 可以依赖数据库的自增主键实现。进行分库分表之后,如果还是用数据库的自增主键,可能会导致主键重复。我们可以通过雪花算法或者美团 Leaf 算法生成唯一主键 ID;
- 跨库跨表关联查询问题:分库分表后,跨库和跨表的查询操作实现起来会比较复杂,我们可以通过冗余额外字段避免跨库关联,或者交给数据库分库分表中间件来实现,也可以将数据全量存储到 ES 中去,通过 ES 进行查询;
- 跨库跨表的排序问题:分库分表以后,数据分散存储到不同的数据库和表中,如果需要对数据列表进行排序时,就变得异常复杂,我们可以通过业务代码或者数据库分库分表中间件分别查询每个子表中的数据,然后汇总进行排序,也可以将数据全量存储到 ES 中去,通过 ES 进行查询;
- 跨库跨表
COUNT查询的问题:分库分表以后,数据分散存储到不同的数据库和表中,如果需要对表进行COUNT查询就会很复杂,我们可以将计数的数据单独存储在一张表里,或者将聚合查询的数据同步到 ES 中,交给 ES 进行查询。