1.为什么要主从读写分离
使用数据库连接池架构图:
大部分系统的访问模型都是读多写少,读写请求的差距可能会达到几个数量级
解决思路:将读写请求分离,可以扩展读请求的从库
2.主从读写分离技术关键点
主库:负责写请求
从库:负责读请求
2.1主从复制(将主库数据同步到从库中)
MySQL主从复制依赖binlog(将MySQL中变化日志记录到磁盘中)
- 主库根据操作生成binlog
- 将binlog从主库同步到从库中(异步的,主库不等待同步完成了)
- 从库创建IO线程拉取binlog,将拉取的binlog写入relay log中
- 主库创建log dump线程发送binlog(不影响主流程)
- 从库新建线程读取relay log内容,并且开始回放,最终实现主从一致(避免实际写入会造成较大延迟)
- 及时主库因写而锁表,也不会影响读
- 读流量增加可以增加从库,同时从库也可以做主库的备份
- 由于从库的数量会决定主库的log dump线程(因此不应该无限扩充从库)
缺点:主从延迟导致的问题,系统变复杂
因为主从延迟导致在读取时无数据
解决方案
| 数据的冗余 | 使用缓存 | 查询主库 | |
|---|---|---|---|
| 实现 | 在消息队列中,存储信息,直接使用 | 在写完数据库后,写入缓冲中,在缓存中查询数据 | 直接查询主库 |
| 优点 | 实现简单,不引入新的组件 | ||
| 缺点 | 导致单条消息较大,增加了消息发送的带宽和时间 | 多写可能导致数据不一致 | 大量的读请求会严重影响主库性能 |
| 推荐 | 1 |
主从延迟导致困难难以排查:需要监控从库落后时间,并及时进行报警
2.2对RD屏蔽开发(读写分离不影响现有代码)
使用数据库中间件解决数据库的读写问题
2.2.1以代码信息内嵌在程序内部
以淘宝的 TDDL( Taobao Distributed Data Layer)为代表,以代码形式内嵌运行在应用程序内部。
优点:简单易用,没有多余的部署成本
缺点:有语言限制
2.2.2单独部署代理层方案
如早期阿里巴巴开源的 Cobar,基于 Cobar 开发出来的 Mycat,360 开源的 Atlas,美团开源的基于 Atlas 开发的 DBProxy 等等
独立部署服务,使用MySQL通信协议,改写SQL并发往机器
优点:支持多种编程语言
缺点:运维复杂,sql需要跨越网络使用,性能有损耗
3.课程小结
- 主从分离可以解决突发的读请求,是横向扩展的方法
- 需要关注主从分离的有延迟
- 可以选择屏蔽读写分离的中间件
思考:
- 需要在数据一致性和性能间取舍
- 数据强一致性,导致性能下降
- 性能高,可能造成同步失败
- 很多组件使用读写分离,导致出现诡异的问题