thinkphp6 接收不到数据_高并发下的 读写分离 主从配置 数据延迟处理方案(之平时幻想)...

88c453cecce1ec6c2ddef9bb400584c4.png

905099c8ff751b4badb272fd9dffe90f.png

高并发下的读写分离:

在生产环境高峰期,MySQL主库有很高的写入,这个时候,主从复制可能会有很大的延时。发现总有一些sql在主库写入更新成功,在select查询从库的时候,由于主从复制存在延迟,读取从库的数据和主库不一致,导致业务产生bug。

业务产生bug的原因是因为数据库采用单一的主从异步复制的架构。

异步模式指的是MySQL主服务器上I/O thread 线程将二进制日志写入binlog文件之后就返回客户端结果,不会考虑slave数据库是否完整的同步数据,同样不会考虑二进制日志是否完整传输到从服务器以及是否完整存放到从服务器上的relay日志中,这种模式一旦高并发下或者主服务器宕机,数据就可能产出主从不一致或者可能会发生丢失。

异步模式是一种基于偏移量的主从复制,实现原理是:

主库开启binlog功能并授权从库连接主库,从库通过change master得到主库的相关同步信息然后连接主库进行验证,主库IO线程根据从库slave线程的请求,从 http:// master.info 开始记录的位置点向下开始取信息,同时把取到的位置点和最新的位置与binlog信息一同发给从库IO线程,从库将相关的sql语句存放在relay-log里面,最终从库的sql线程将relay-log里的sql语句应用到从库上,至此整个同步过程完成,之后将是无限重复上述过程。

一. MySQL的解决办法:

MySQL 实际上在这一块有两个机制:

1.一个是半同步复制,用来解决主从同步延时问题。

从MySQL5.5开始,MySQL以插件的形式支持半同步复制。MySQL 5.7极大的提升了半同步复制的性能。

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用

2.一个是并行复制(全同步复制,多线程复制),用来解决主从同步延时问题。

在MySQL 5.7中,引入了基于组提交的并行复制(Enhanced Multi-threaded Slaves),设置参数slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,即可支持一个schema下,slave_parallel_workers个的worker线程并发执行relay log中主库提交的事务。

其核心思想:一个组提交的事务都是可以并行回放(配合binary log group commit);slave机器的relay log中 last_committed相同的事务(sequence_num不同)可以并发执行。

具体配置如下:

其中,变量slave-parallel-type可以有两个值:DATABASE 默认值,基于库的并行复制方式;LOGICAL_CLOCK:基于组提交的并行复制方式

MySQL 5.7开启Enhanced Multi-Threaded Slave配置:

# slave
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

至此,MySQL彻底解决了复制延迟问题,可喜可贺!

(由于没有MySQL5.7的版本,本人并没有亲自实践过,待验证,但是原理基本是这样的...)

二. PHP框架解决:

当我们在写代码的时候,需要sql插入数据然后立刻查询出结果做判断。在读写分离的情况下,如果了解到,在运行的生产的数据库存在主从数据延迟,对这种查询可以设置直连主库,也就是说,这种情况下,读也是读取的主库。

下面是ThinkPHP6.0的解决办法:

有些情况下,需要直接从主库读取数据,例如刚写入数据之后,从库数据还没来得及同步完成,你可以使用

Db::name('user')
    ->where('id', 1)
    ->update(['name' => 'thinkphp']);
Db::name('user')
    ->master(true)
    ->find(1);

不过,实际情况远比这个要复杂,因为你并不清楚后续的方法里面是否还存在相关查询操作,这个时候我们可以配置开启数据库的read_master配置参数。

// 开启自动主库读取
'read_master' => true,

开启后,一旦我们对某个数据表进行了写操作,那么当前请求的后续所有对该表的查询都会使用主库读取。

当然这样操作,读写分离就失去了部分意义...

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值