为了进一步的降低数据库端的压力(高并发的瓶颈),这个时候也会在业务层部署分布式缓存集群(redis、memcached)等,把读的压力转移给应用服务器端,其实与数据主从的设计是遵循同一个原则,降低后端数据库的压力。
主要解决问题为:由于延时(网络传输,操作)而引起的数据库主从不一致的问题
解决方案:
1、半同步复制(详见最下面)
办法就是等主从同步完成之后,等主库上的写请求再返回,这就是常说的“半同步复制”。
服务层去写主数据库、然后复制给从数据库。再由服务层去读从数据库
原理: 事务在主库写完binlog后需要从库返回一个已接受,才放回给客户端。 确保事务提交后binlog至少传输到一个从库,半同步模式不是mysql内置的,从mysql 5.5开始集成,需要master 和slave 安装插件开启半同步模式
优点:以插件形式存在,需单独安装。是数据库原生功能,比较简单
缺点:性能有一定程度的降低,时间延迟,至少是一个tcp/ip往返的时间。网络异常或从库宕机,卡主库,直到超时或从库恢复(可设置超时时间、超时就变成异步复制,性能高,数据一致性最差)。
2、异步复制
MySQL默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从库上。
3、组复制MySQL Group Replication(MGR)
MySQL在引擎层完成Prepare操作写Redo日志之后,会被MySQL的预设Hook拦截进入MGR层
MGR层将事务信息打包通过Paxos协议发送到全部节点上,只要集群中过半节点回复ACK,那么将告诉所有节点数据包同步成功,然后每个节点开始自己认证(certify)通过就开始写Binlog,提交事务或者写relay log,数据同步,如果认证不通过则rollback
优点:
数据一致性较好
缺点:
性能不高
TP999升高,吞吐量降低;增大20%~30%响应时间
4、使用数据库中间件
流程:
1、所有的读写都走数据库中间件,通常情况下,写请求路由到主库,读请求路由到从库
2、记录所有路由到写库的key,在主从同步时间窗口内(假设是500ms),如果有读请求访问中间件,此时有可能从库还是旧数据,就把这个key上的读请求路由到主库。
3、在主从同步时间过完后,对应key的读请求继续路由到从库。
相关的中间件:
1、canal:是阿里巴巴旗下的一款开源项目,纯Java开发,基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了MySQL。
2、otter:也是阿里开源的一个分布式数据库同步系统,尤其是在跨机房数据库同步方面,有很强大的功能。它是基于数据库增量日志解析,实时将数据同步到本机房或跨机房的。
优点:能保证绝对一致
缺点:中间件成本较高
5、缓存记录写key
如果key要发生写操作,记录在cache里,并设置“经验主从同步时间”的cache超时时间,例如500ms,然后修改数据库
读操作先到缓存里查看对应的key有没有数据,如果有数据说明刚刚发生写操作,此时需要切换主数据库进行操作,如果没有命中数据,说明这个key近期没有进行写操作,此时切换到从数据库进行读操作。
优点:相对数据库中间件,成本较低
缺点:为保证一致性,引入cache组件,并且读写都多了缓存操作。
1、半同步复制
流程图:
Master处理事务过程中,提交完事务后,必须等至少一个Slave将收到的binlog写入relay log返回ack才能继续执行处理用户的事务。
配置:
rpl_semi_sync_master_wait_point = AFTER_COMMIT (什么时间点开始等ack)【这里MySQL 5.5并没有这个配置,MySQL5.7 为了解决半同步的问题而设置的,增强半同步】
rpl_semi_sync_master_wait_for_slave_count = 1 (最低必须收到多少个slave的ack)
rpl_semi_sync_master_timeout = 100(等待ack的超时时间)
半同步问题:
1、一旦Ack超时,将退化为异步复制模式,那么异步复制的问题也将发送
2、性能下降,增多至少一个RTT时间
3、数据不一致性问题,因为等待ACK的点是Commit之后,此时Master已经完成数据变更,用户已经可以看到最新数据,当Binlog还未同步到Slave时,发生主从切换,那么此时从库是没有这个最新数据的,用户又看到老数据。
2、增强半同步复制:(增强半同步,唯一不同点是等待ack响应的时间点不同)
流程图
设置:
rpl_semi_sync_master_wait_point = AFTER_SYNC(与半同步复制唯一区别)
增强半同步将等待ACK的点放在提交Commit之前,此时数据还未被提交,外界看不到数据变更,此时如果发送主从切换,新库依然还是老数据,不存在数据不一致的问题。
如果多个用户同时发起写请求,为避免数据有误(插入先后顺序问题,可采用“并行复制”,mysql 5.7之后应用)
问题:
1、一旦Ack超时,将退化为异步复制模式,那么异步复制的问题也将发送
2、性能下降,增多至少一个RTT时间
3、如果超时时间设置很大,然后因为网络原来长时间收不到ACK,用户提交是被挂起的,可用性收到打击(半同步一样存在)
半同步复制、增强半同步复制参考链接:
https://blog.csdn.net/qq_33330687/article/details/107496954
3、并行复制:
MySQL 5.7必须打开MTS功能,并升级到至少5.7.19版本;
MySQL 8.0的writeset MTS是解决主从延迟的最终形态;
参考链接:
https://blog.csdn.net/andong154564667/article/details/82117727
https://mp.weixin.qq.com/s/NwFGER-qn2xQ5TnG-php1Q
感谢博主,喝杯咖啡~
感谢博主,喝杯咖啡~
还没有人发表评论