读写分离数据库如何保持数据一致性

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

  1. 读请求,直接读从库
  2. 写请求,先写入主库,然后主库将数据同步到其他从库

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

缓存标记法

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

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

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

本地缓存标记

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

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