【二十四】redis之缓存与数据的一致性(DTP)

分布式的数据库保证数据一致性,如果有分布式事务是最好,或者XA这种分布式事务也挺好。

但是这里说的可以粗暴的理解成redis作为缓存使用的时候如何保证redis和mysql中数据的一致性。

一、读操作

读操作都没什么大的分歧,一般都是先读redis,redis没有就读mysql,然后把读出来的数据写到redis中。

二、先删除redis,再更新mysql

即使写mysql失败了,也没关系,大不了就是redis被删了,下次查询要读mysql而已。

这个操作有个问题需要解决。

问题场景:

比如说,有一条数据,在redis和mysql中存的都是id和age的对应。

现id=1 age=3。

线程A写操作,线程B读操作,并发执行。

线程A要把id=1的数据它的age=3改成age=4,它先删除了redis中id=1的数据

此时线程B并发执行,线程B查redis发现id=1的数据没有,线程B查询mysql(select普通查询查的是快照并不需要加锁, 事务隔离机制是RR)的到id=1的数据age=3,然后线程B把id=1的数据age=3写到redis中。

线程A给mysql中id=1的这条记录加了排他锁。此时线程A把mysql中id=1的数据改成age=4。

这就造成了数据不一致。一直要到该缓存到了失效的时间才有可能让redis和mysql的数据一直。

解决方案:(读/写请求串行化)

同一个数据唯一id每次都打在同一个service机器上,在service机器中同一个数据唯一id每次都用同一个数据库连接。

这样可以保证对同一个数据唯一id的数据每次在mysql中的读写都是串行的。

比如

1.在用哪个service的时候根据数据id取模来决定

获取Service连接的CPool.GetServiceConnection()【返回任何一个可用Service连接】

改为CPool.GetServiceConnection(longid)【返回id取模相关联的Service连接】

2.在service中获取数据库连接的时候也根据数据id取模来决定

获取DB连接的CPool.GetDBConnection()【返回任何一个可用DB连接】

改为CPool.GetDBConnection(longid)【返回id取模相关联的DB连接】

这个问题详细解释看这篇博客:https://www.cnblogs.com/duanxz/p/3783369.html 

 三、Cache Aside 先更新数据库,再删除redis(推荐)

 这种操作需要把更新数据库mysql和删除redis放在同一个mysql的事务当中。

这样的好处是保证数据一致性,如果更新mysql成功,删除redis失败报错,mysql这个更新事务会回滚。

这里同样可能出现一个问题

问题场景:

比如说,有一条数据,在mysql中存的id和age对应。

现id=1 age=3。

线程A写操作,线程B读操作,并发执行。

线程A给mysql中id=1的数据加上了排他锁,更新age=4,删除redis,此时事务并没有结束。

此时线程B读redis发现没有,线程B去读mysql(隔离级别RR),这里是select快照读,不需要加锁,读到id=1的数据age=3,写到redis中。

这也造成了redis和mysql的数据不一致

解决方案:

读加共享锁,读和写必须互斥

比如不要用select快照读,用select lock in share mode读的时候加上共享锁。

四、Read/Write through(缓存代理)

Read/Write Through套路是把更新数据库(mysql)的操作由缓存自己代理了。

不用业务系统来维护数据库和缓存的数据一致性。

but~如果缓存是选主用redis,redis并不支持缓存代理,换句话说redis并不会帮业务系统维护redis和mysql数据的一致性

五、Write behind caching(写缓存异步刷库)

在更新数据的时候,只更新缓存,不更新数据库,另外有个线程或者进程异步的把缓存批量更新到数据库。

比如业务系统中另外写个线程定时把redis的数据刷新到mysql中

问题场景:

redis死了,数据丢了

解决方案:

redis做持久化。使用aof的always才能保证恢复数据的时候不会有数据丢失。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值