毕节做网站,中山做网站多少钱,网站编写语言,开鲁网站seo目录 前言
更新数据库更新缓存#xff1a;
1.在更新缓存前先加一个分布式锁
2.在更新完缓存时#xff0c;给缓存加上较短的过期时间
Cache Aside策略
1.先删除缓存#xff0c;再更新数据库
延迟双删
2.先更新数据库#xff0c;再删除缓存
保证两个操作都能执行成功…目录 前言
更新数据库更新缓存
1.在更新缓存前先加一个分布式锁
2.在更新完缓存时给缓存加上较短的过期时间
Cache Aside策略
1.先删除缓存再更新数据库
延迟双删
2.先更新数据库再删除缓存
保证两个操作都能执行成功
重试机制
订阅MySQLbinlog再操作缓存 总结 前言
由于引入了缓存那么在数据更新时不仅要更新数据库而且要更新缓存这两个更新操作存在前后的问题 先更新数据库再更新缓存先更新缓存再更新数据库
但是会因为并发问题造成缓存和数据库的数据不一致的现象。
如果先更新缓存在更新数据库可能会出现下图 缓存和数据库中的数据依然可能不一致。
出现并发问题的时候当两个请求并发更新同一条数据时可能会出现缓存和数据库中的数据不一致的现象。
更新数据库更新缓存
如果先更新数据库再更新缓存可能会出现下图情况 此时数据库中的数据是 2而缓存中的数据却是 1出现了缓存和数据库中的数据不一致的现象。
如果业务对缓存命中率有很高的要求我们也可以采用这个方案。
如何解决这个方式的数据不一致的问题
1.在更新缓存前先加一个分布式锁
保证同一时间只运行一个请求更新缓存就不会产生并发问题了当然引入了锁后对于写入的性能就会带来影响。
2.在更新完缓存时给缓存加上较短的过期时间
这样出现缓存不一致的时候缓存数据也能很快过期对业务还是能接受的。 Cache Aside策略
不更新缓存而是删除缓存中的数据然后到读取数据时发现缓存中没数据之后再从数据库中读取数据并更新到缓存中。
写策略与读策略 1.先删除缓存再更新数据库
依然在读写并发时还是会出现缓存和数据库的数据不一致的问题。 针对读写的并发请求而造成不一致的解决办法是
延迟双删
伪代码
#删除缓存
redis.delKey(X)
#更新数据库
db.update(X)
#睡眠
Thread.sleep(N)
#再删除缓存
redis.delKey(X)
加了个睡眠时间主要是为了确保请求 A 在睡眠的时候请求 B 能够在这这一段时间完成「从数据库读取数据再把缺失的缓存写入缓存」的操作然后请求 A 睡眠完再删除缓存。
所以请求 A 的睡眠时间就需要大于请求 B 「从数据库读取数据 写入缓存」的时间。
但是具体睡眠多久其实是个玄学很难评估出来所以这个方案也只是尽可能保证一致性而已极端情况下依然也会出现缓存不一致的现象。
因此还是比较建议用「先更新数据库再删除缓存」的方案。
2.先更新数据库再删除缓存 还是会出现不一致的问题但这个概率不高因为缓存的写入通常要远远快于数据库的写入所以先更新数据库再删除缓存是可以保证数据一致性的。
还可以给缓存数据加上过期时间就算在这期间存在缓存数据不一致经过过期时间最终还是能达到一致。
但是这个依然会遇到问题当删除缓存失败时缓存中的数据依然是旧数据没有更新。再给缓存加上过期时间后还要等一段时间才能更新生效的现象。
保证两个操作都能执行成功
通过重试机制和订阅MySQL binlog再操作缓存的方式都可以保证两个操作都能成功。
重试机制
引入消息队列将第二个操作删除缓存要操作的数据加入到消息队列有消费者来操作数据。
如果应用删除缓存失败可以从消息队列中重新读取数据然后再次删除缓存。如果重试超过一定次数还没有成功就需要向业务层发送报错信息。
如果删除缓存成功就要把数据从消息队列中移除避免重复操作。 订阅MySQLbinlog再操作缓存
「先更新数据库再删缓存」的策略的第一步是更新数据库那么更新数据库成功就会产生一条变更日志记录在 binlog 里。
于是我们就可以通过订阅 binlog 日志拿到具体要操作的数据然后再执行缓存删除阿里巴巴开源的 Canal 中间件就是基于这个实现的。
Canal 模拟 MySQL 主从复制的交互协议把自己伪装成一个 MySQL 的从节点向 MySQL 主节点发送 dump 请求MySQL 收到请求后就会开始推送 Binlog 给 CanalCanal 解析 Binlog 字节流之后转换为便于读取的结构化数据供下游程序订阅使用。 所以如果要想保证「先更新数据库再删缓存」策略第二个操作能执行成功我们可以使用「消息队列来重试缓存的删除」或者「订阅 MySQL binlog 再操作缓存」这两种方法有一个共同的特点都是采用异步操作缓存。 总结
数据库和缓存保持一致性
方式问题解决 先更新缓存 再更新数据库 数据不一致并发问题暂无 先更新数据库 再更新缓存 同上 1.在更新缓存前加上分布式锁 2.给缓存加上较短的过期时间。 先删除缓存 再更新数据库 数据不一致读写并发延迟双删 先更新数据库 再删除缓存 同上 1.重试机制 2.订阅MySQL binlog再操作缓存。 啊这个要记好多回头再来背一遍。