移动端网站开发语言,邢台招聘信息最新招聘2023,万网 公司网站链接,中国电商平台概念#xff1a; 当修改了数据库的数据也要同时更新缓存的数据#xff0c;缓存和数据库的数据要保持一致
那为什么会有不一致的情况呢#xff1f;
如果不追求一致性#xff0c;正常有两种做法
先修改数据库 后删除旧的缓存先删除旧的缓存 再修改数据库
我们以先删除旧的…概念 当修改了数据库的数据也要同时更新缓存的数据缓存和数据库的数据要保持一致
那为什么会有不一致的情况呢
如果不追求一致性正常有两种做法
先修改数据库 后删除旧的缓存先删除旧的缓存 再修改数据库
我们以先删除旧的缓存再修改数据库为例
当 线程1 要对数据库做更新操作的时候先将Redis中旧的缓存删掉不巧此时线程之间发生切换线程2读取缓存因为被线程1删掉了所以缓存未命中线程2就直接查询数据库并重建缓存将此时的数据库数据写回Redis接着又切换回线程1线程1将数据库中的数据修改为新的值
此时就出现了数据库和缓存中的数据不一致的问题
因此我们不能只进行一次缓存删除操作要使用双删的方法
比如先删除旧的缓存修改完数据库后再删除一次缓存
但是单纯双删不能解决问题比如
当 线程1 要对数据库做更新操作的时候先将Redis中旧的缓存删掉不巧此时线程之间发生切换线程2读取缓存因为被线程1删掉了所以缓存未命中线程2就直接查询数据库获取当前数据库的值但未重建缓存接着又切换回线程1线程1将数据库中的数据修改为新的值并再次删除缓存此时又切换为线程2线程2将当时读取到的值写回Redis又造成了数据不一致
因此我们可以采取 延迟双删策略
还是上面那个例子
当 线程1 要对数据库做更新操作的时候先将Redis中旧的缓存删掉不巧此时线程之间发生切换线程2读取缓存因为被线程1删掉了所以缓存未命中线程2就直接查询数据库获取当前数据库的值但未重建缓存接着又切换回线程1线程1将数据库中的数据修改为新的值但不马上删除缓存而是等待一段时间切换为线程2线程2将当时读取到的值写回Redis最后切换回线程1线程1再将Redis中的数据删除
可以看到 延迟双删策略 确实能解决数据一致性的问题但延迟的时间很难确定短了怕上面的例子中第6步先于第5步执行长了怕在第5步和第6步之间的数据不一致状态持续时间太长
因此我们需要另外的解决方案
针对双写一致性有两种场景 一致性要求高 和 允许短暂不一致
这两种场景的解决方案不同
一致性要求高
可以使用如下的分布式锁方案 但是我们可以看到该方案让并发变为了串行极大降低了性能
因此我们可以使用读写锁
读锁 readLock 加了读锁之后其他线程还能继续加读锁和读数据但是不能写也不能加写锁
写锁 writeLock写锁是排他锁加锁之后其他线程阻塞不能进行读写操作
Redission 以及实现了读写锁
代码实例
读锁 写锁 其中 redissonClient.getReadWriteLock()中传入的值必须是一样的
允许短暂不一致
实际上的开发过程中这种场景才是主流
这种场景的解决方法很多比较常用的方法是 异步通知保持数据的最终一致性
流程图如下 修改数据库时需要发送修改记录给MQ缓存服务需要监听MQ根据MQ中的修改记录更新缓存