对于一些关键数据, 例如账户数据, 对可靠性和一致性的要求非常高. 我们宁可牺牲短暂时间内的可用性, 也不允许数据出现错误或丢失. 所以早期我们会发现业界存在这种现象: DB 设置了主备同步, 主 DB 挂了, 但是不敢切换到备 DB, 只能暂停服务. 这种现象的主要原因有两点:
主备 DB 同步是异步的, 将备 DB 提升为主 DB, 可能造成未同步数据的丢失.
即使主备 DB 同步已全部完成, 将备 DB 提升为主 DB 后会变成单点. 假如新的主 DB 也发生故障, 单点期间的数据可能丢失.
1. Master 故障后单点问题
问题二很好解决, 只要设置双备机即可 (三台机器分布在不同 IDC). 当主机故障后, 在确认数据同步已全部完成后 (只需其中一台备机全部完成即可), 将已同步全部数据的备机提升为主机, 另一台备机切换同步源为新主机即可. 假如新主机再次故障, 那么也只能暂停服务. 在考虑 IDC 分布之后, 两台机器同时故障的概率比单台机器故障的概率小很多, 所以可以大大提升系统可用性.
2. Master 故障时数据同步问题
对于问题一, 可以使用 MySQL 5.5 以上版本的半同步复制功能解决.
2.1 MySQL 半同步复制机制
image.png
MySQL 半同步复制和异步复制的差别如上述架构图所示: 在异步复制的情况下, MySQL Master Server 将自己的 binlog 通过复制线程传输出去以后, MySQL Master Sever 就自动返回数据给客户端, 而不管 slave 上是否接受到了这个二进制日志. 在半同步复制的架构下, 当 master 在将自己 binlog 发给 slave 上的时候, 要确保 slave 已经接受到了这个二进制日志以后, 才会返回数据给客户端. 对比两种架构: 异步复制对于用户来说, 可以确保得到快速的响应结构, 但是不能确保二进制日志确实到达了 slave 上; 半同步复制对于客户的请求响应稍微慢点, 但是他可以保证二进制日志的完整性.
利用半同步复制机制, 我们就可以保证每条数据提交都能至少同步到一台备机上了.
2.2 半同步复制机制的退化
从上面的描述看, 好像是同步复制, 那为什么叫做半同步复制呢, 主要是因为还有另外一个退化机制, 当达到触发条件时, 同步复制会退化为异步复制, 所以叫做半同步复制. 具体退化机制如下:
半同步复制需要设置一个超时时间, 在超时时间内, 数据采用上述的同步复制模式, 只需要有至少一台备机接收了 binlog, 数据即可提交成功. 假如在超时时间内所有备机都没有响应, 那么会退化为异步复制模式, 并继续提供服务.
由于我们需要的是同步复制 (确切的说, 是至少一台备机同步复制, 其余备机异步复制), 那么就应该避免退化的出现, 可以通过设置足够长的超时时间来实现. 这样, 当所有备机都没有响应时, 数据提交就会失败, 也就避免了数据不一致的现象. 至于提交失败的处理, 当然是像各银行一样, 要求用户稍后再重试了.
相信我, 告诉用户系统繁忙, 总好过告诉用户他的钱不见了要好!
来源: https://www.qcloud.com/developer/article/1338800