面试题答案
一键面试系统架构层面
- 负载均衡
- 策略:使用诸如 HAProxy、Keepalived 等工具实现负载均衡。对于读请求,根据从库的负载情况,将请求均匀分配到不同的从库;对于写请求,主要发往主库。
- 实现方式:以 HAProxy 为例,配置
frontend
定义监听的 IP 和端口,backend
定义后端服务器池,在后端针对主从库分别配置不同的权重等参数来控制流量分配。
- 主从复制优化
- 策略:采用半同步复制,确保主库提交事务时至少有一个从库接收到并写入中继日志,提高数据一致性;同时调整主从复制线程数量,根据服务器性能合理分配。
- 实现方式:在主库配置
rpl_semi_sync_master_enabled=1
,从库配置rpl_semi_sync_slave_enabled=1
;通过show variables like '%slave_parallel_workers%'
查看和设置从库并行复制线程数。
- 分布式缓存
- 策略:引入 Redis 等分布式缓存,将热点数据缓存起来,减少对数据库的读压力。
- 实现方式:在应用层,使用 Redis 客户端库,如 Jedis(Java)、redis - py(Python)等,先从缓存中读取数据,若缓存未命中再查询数据库,并将查询结果写入缓存。
SQL 语句优化层面
- 索引优化
- 策略:分析查询语句,为经常用于
WHERE
、JOIN
、ORDER BY
等子句的列创建合适的索引。避免索引过多导致写性能下降。 - 实现方式:使用
EXPLAIN
关键字分析 SQL 语句执行计划,查看索引使用情况。通过CREATE INDEX index_name ON table_name (column_name)
创建索引。
- 策略:分析查询语句,为经常用于
- 查询语句改写
- 策略:避免使用子查询,尽量改写为
JOIN
;减少SELECT *
,只选择需要的列;对于分页查询,使用LIMIT OFFSET
优化时,若OFFSET
过大,可使用基于书签的分页(如记录上次查询的最大 ID)。 - 实现方式:例如将
SELECT column1 FROM table1 WHERE column2 IN (SELECT column2 FROM table2)
改写为SELECT table1.column1 FROM table1 JOIN table2 ON table1.column2 = table2.column2
。
- 策略:避免使用子查询,尽量改写为
存储引擎配置层面
- InnoDB 配置优化
- 策略:调整
innodb_buffer_pool_size
,使其能容纳尽可能多的数据和索引,提高缓存命中率;合理设置innodb_log_file_size
和innodb_log_files_in_group
,优化日志写入性能。 - 实现方式:在
my.cnf
配置文件中设置innodb_buffer_pool_size = 8G
(根据服务器内存调整),innodb_log_file_size = 256M
,innodb_log_files_in_group = 2
等参数。
- 策略:调整
可能带来的风险及规避手段
- 数据一致性风险
- 风险:半同步复制虽然提高了一致性,但仍存在一定时间窗口内主从数据不一致;分布式缓存也可能存在缓存与数据库数据不一致的情况。
- 规避手段:对于半同步复制,可设置合理的超时时间,若超时未收到从库确认,可采取降级为异步复制或暂停主库写操作等措施;对于缓存一致性问题,采用缓存更新策略,如读写时都更新缓存,或使用缓存失效机制,定期清理缓存。
- 单点故障风险
- 风险:负载均衡器可能成为单点,若其故障,整个系统的请求分发将受影响;主库故障也会导致写操作中断。
- 规避手段:对负载均衡器采用主备或多活模式,如 Keepalived 的主备配置;对于主库故障,采用自动故障切换机制,如 MHA(Master High Availability),能快速检测主库故障并将从库提升为主库。
- 索引维护风险
- 风险:过多索引会增加写操作的开销,如插入、更新、删除数据时,除了数据本身的操作,还需更新索引,影响写性能。
- 规避手段:定期使用
pt - index - advisor
等工具分析索引使用情况,删除不必要的索引;在进行大量数据写入操作前,可先删除部分非必要索引,操作完成后再重新创建。