在企业开发过程中,数据库属于非常重要的一环,而MySQL作为最为常见的关系型数据库(之一),在日常使用过程中通常是单机的,很容易造成单点故障问题,这篇文章便是我对于MySQL集群学习的一些思考和总结
定义
读写分离是一种很经典的数据库拆分方案,将MySQL集群中的节点分为主库和从库,主库负责写,从库负责读
问题1:如何保证写请求打到主库,读请求打到从库?
1. 程序实现
由开发人员实现,在代码中根据SQL语句进行分发:insert、delete、update请求打到主节点上,select请求打到从节点上
解决方案:当当网的Sharding-JDBC 、阿里的TDDL
2. 基于中间代理层实现
上面那种方式需要修改代码,在业务代码中进行判断
在架构的思想中,有一句话:没有什么是加一层解决不了的,如果有,那就再加一层(此话来自狂神),这种基于中间代理层的方式一般就是在应用服务器和数据库服务器之间加了一层,代理数据库服务器接收到应用服务器的请求后根据判断后转发到后端数据库
解决方案:Mycat 、360的Atlas、网易的DDB
问题2:如何保证主节点和从节点的数据一致性?
基于binlog实现,从服务器向主服务器请求binlog日志文件,主服务器会把这个 bin 日志复制到从服务器上执行一遍,这样从服务器上的数据就和主服务器上的数据相同了
复制过程由3个线程保证
- Slave SQL线程:创建用于读取relay log中继日志并执行日志中包含的更新,位于slave端
- Slave I/O线程:读取 master 服务器Binlog Dump线程发送的内容并保存到slave服务器的relay log中继日志中,位于slave端:
- Master Binlog dump线程:将bin-log二进制日志中的内容发送到slave服务器,位于master端
注意:如果一台主服务器配两台从服务器那主服务器上就会有两个Binlog dump 线程,而每个从服务器上各自有两个线程
主从复制实现步骤
- 主服务器开启binlog,记录任何修改了数据库数据的事件
- 从服务器开启一个IO线程,扮演MySQL客户端,请求主服务器的binlog日志文件
- 主线程开启一个Dump线程,检查自己binglog日志中的事件,跟对方请求的位置对比;如果不带请求位置参数,则主服务器就会从第一个日志文件中的第一个事件一个一个发送给从服务器
- 从服务器接收到主服务器发送过来的数据把它放置到中继日志(relay log)文件中,并记录该次请求到主服务器的具体哪一个二进制日志文件内部的哪一个位置
- 从服务器启动另外一个SQL线程,把 relay log 中的事件读取出来,并在本地再执行一次