读写分离
读写分离
读写分离:将对数据库的读写操作分散到不同的数据库节点上,可以小幅提升写性能,大幅提升读性能。
MySQL里通常是基于主从复制实现的:
- 主库(Master):负责处理写操作(INSERT、UPDATE、DELETE)
- 从库(Slave):负责处理读操作(SELECT)
- 应用层或中间件做路由
一般都是一主多从,主库和从库之间会进行数据同步
实现读写分离有两种常见方式:
- 代理方式
- 组件方式
代理方式
代理方式:在应用和数据库之间引入一个代理层,这个代理负责将读写请求路由到正确的数据库节点。
常见的代理工具有:
- MySQL Router(官方,MySQL Proxy的替代方案)
- Atlas(基于MySQL Proxy的开源项目)
- MaxScale
- MyCat
组件方式
组件方式:在应用层直接使用支持读写分离的数据库连接池或ORM框架。
推荐使用:sharding-jdbc(阿里巴巴开源的分库分表组件)
主从复制原理
MySQL的主从复制基于二进制日志(binlog)实现,binlog主要记录了MySQL数据库中数据的所有变化(数据库执行的所有DDL和DML语句)。
详细过程:

- 主库将数据库中数据的变化写入到binlog中
- 从库连接主库
- 从库会创建一个I/O线程向主库请求更新的binlog
- 主库会创建一个binlog dump线程,将binlog发送给从库,从库中的I/O线程负责接收
- 从库的I/O线程将接收的binlog写入到从库的中继日志(relay log)中
- 从库的SQL线程读取中继日志,并执行其中的SQL语句,从而实现数据同步
如何避免主从延迟
强制将读请求路由到主库处理:
例如:
- 用户下单
- 紧接着查订单状态
这种场景必须读主库
比如通过Sharding-JDBC的HintManager分片键值管理器,我们可以强制使用主库:
1 | HintManager hintManager = HintManager.getInstance(); |
延迟读取
比如:
主从同步延迟0.5s,那就1s后再读从库。
