mysql读写分离,以及保证保持数据一致性实现方案

首先,说一下读写分离实现原理:
主数据库负责写入操作,从(子)数据库负责读取操作;

然后读写分离的核心是主从同步,也就是主数据库与从数据库的实时数据同步方案。

1、什么是mysql主从同步?

当master(主)库的数据发生变化的时候,变化会实时的同步到slave(从)库。

2、主从同步有什么好处?

水平扩展数据库的负载能力。
容错,高可用。Failover(失败切换)/High Availability
数据备份。
3、主从同步的原理是什么?

首先我们来了解master-slave的体系结构。

如下图:
在这里插入图片描述

不管是delete、update、insert,还是创建函数、存储过程,所有的操作都在master上。当master有操作的时候,slave会快速的接收到这些操作,从而做同步。

但是,这个机制是怎么实现的呢?

在master机器上,主从同步事件会被写到特殊的log文件中(binary-log);在slave机器上,slave读取主从同步事件,并根据读取的事件变化,在slave库上做相应的更改。

如此,就实现了主从同步了!

下面我们来详细的了解。

3.1主从同步事件有哪些

上面说到:

在master机器上,主从同步事件会被写到特殊的log文件中(binary-log);

主从同步事件有3种形式:statement、row、mixed。

statement:会将对数据库操作的sql语句写入到binlog中。
row:会将每一条数据的变化写入到binlog中。
mixed:statement与row的混合。Mysql决定什么时候写statement格式的,什么时候写row格式的binlog。
3.2在master机器上的操作

当master上的数据发生改变的时候,该事件(insert、update、delete)变化会按照顺序写入到binlog中。

binlog dump线程

当slave连接到master的时候,master机器会为slave开启binlog dump线程。当master 的 binlog发生变化的时候,binlog dump线程会通知slave,并将相应的binlog内容发送给slave。

3.3在slave机器上的操作

当主从同步开启的时候,slave上会创建2个线程。

I/O线程。该线程连接到master机器,master机器上的binlog dump线程会将binlog的内容发送给该I/O线程。该I/O线程接收到binlog内容后,再将内容写入到本地的relay log。
SQL线程。该线程读取I/O线程写入的relay log。并且根据relay log的内容对slave数据库做相应的操作。
3.4如何在master、slave上查看上述的线程?

使用SHOW PROCESSLIST命令可以查看。

如图,在master机器上查看binlog dump线程。

在这里插入图片描述

如图,在slave机器上查看I/O、SQL线程。
在这里插入图片描述

4、讲了这么多,一图以蔽之
在这里插入图片描述

数据库读写分离主要解决高并发时,提高系统的吞吐量。因为大部分场景下都是读多写少。下图是数据库读写分离模型。
在这里插入图片描述

每次请求打到这个系统后:

读请求,直接读从库
写请求,先写入主库,然后主库将数据同步到其他从库
在高并发或者网络状况不理想时,写完数据后,主库还没来得及将数据同步到从库,其他读请求去读从库,发现从库中的数据仍然是旧数据。这就是读写分离数据库数据不一致的根本原因。
下面给出两种方案去解决这个问题:

缓存标记法
在这里插入图片描述

上图流程:
1)A发起写请求,更新了主库,再在缓存中设置一个标记,代表此数据已经更新,标记格式( 用户ID+业务ID+其他业务维度)
2)设置此标记,要加上过期时间,可以为预估的主库和从库同步延迟的时间
3)B发起读请求的时候,先判断此请求的业务在缓存中有没有更新标记
4)如果存在标记,走主库;如果没有走从库。

这个方案就有效了解决了数据不一致的问题。
但这个方案会有个严重的问题,也就是每次的读请求都要到缓存中去判断是否存在缓存标记,如果是单机部署用的是jvm缓存,对性能还好;但如果是集群部署缓存肯定用redis,每次读都要和redis进行交互,这样肯定会影响系统吞吐量。

那么解决这个问题可以用下面这个方案

本地缓存标记
在这里插入图片描述

上图流程:
1)用户A发起写请求,更新了主库,并在客户端设置标记,过期时间(预估的主库和从库同步延迟的时间),可以使用cookie实现
2)用户A再发起读请求时,带上这个cookie
3)服务器处理请求时,获取请求传过来的数据,看有没有这个标记
4)有这个业务标记,走主库;没有走从库。

这个方案就保证了用户A的读请求肯定是数据一致的,而且没有性能问题,因为标记是本地客户端传过去的。
但是无法保证其他用户读数据是一致的,但是实际场景很少需要保持其他用户也保持强一致。延迟个几秒也没问题。

### MySQL读写分离架构中的数据一致性保障 #### 1. 主从复制延迟监控与处理 为了应对主从服务器间的数据延迟,在实际应用中应设置合理的监控机制来检测并报警。当发现较大延迟时,可以通过调整优化SQL语句、增加硬件资源等方式减少延迟时间[^3]。 #### 2. 合理规划业务逻辑设计 针对不同的应用场景合理分配查询请求至主节点还是只读副本。对于那些对实时性有较高需求的操作(如交易类系统),应当直接访问主库;而对于一些允许存在一定滞后性的报表统计分析,则可优先考虑副本来减轻主库压力[^2]。 #### 3. 使用全局事务ID (GTID) 通过启用MySQL GTID特性可以在一定程度上简化跨多个实例间的复制流程,并有助于维护更稳定的一致状态。GTID能够自动解决部分因网络波动等原因造成的断点续传问题,从而增强系统的可靠性和恢复能力[^1]。 ```sql -- 开启gtid模式 SET GLOBAL gtid_mode=ON; ``` #### 4. 配置半同步复制 采用半同步方式代替默认异步模式可以有效降低甚至消除由传统异步复制带来的潜在风险。在这种情况下,只有当至少有一个备机确认接收到更新日志之后才会向客户端返回成功响应,这大大提高了安全性的同时也牺牲了一定程度上的吞吐量性能[^5]。 ```bash # 安装插件 INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; # 设置参数 SET GLOBAL rpl_semi_sync_master_enabled = ON; SET GLOBAL rpl_semi_sync_slave_enabled = ON; ``` #### 5. 建立完善的灾难恢复预案 考虑到可能出现的各种意外情况,比如主机故障转移期间可能发生的数据不一致现象,事先制定详尽有效的应急措施至关重要。定期备份重要资料、测试冷热迁移方案以及培训相关人员都是必不可少的工作环节之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值