资讯

展开

redis和数据库的一致性问题的解决方案

作者:快盘下载 人气:

当前没有框架能够保证redis的数据和数据库的完全一致性;所以需要 我们自己在性能和一致性上作取舍。

使用到缓存的场景

	这里讲到的是缓存和数据库的一致性问题。
	当查询数据库数据的时候;才涉及到缓存的利用上;所以缓存的引入是为了让查询数据的时候提高效率;
    而当发生增、删、改数据的时候;对于缓存来说是要让数据库和缓存发生一致性的改变;进而能让缓存在数据查询时候能继续起作用。

下图就是两种在redis缓存数据库内容时的使用。
redis和数据库的一致性问题的解决方案

对于缓存的一致性操作的选择

明确了缓存的使命------在查询数据库信息时;提前将数据进行缓存;既减少了数据库io;也提高了查询效率。

那么如一个节点的两个图;
缓存的生成;是在首次查询或者缓存过期时间到或者缓存被其他业务删除;进而需要在数据库查询完毕之后;将数据库内容同步到缓存中。
那当数据发生增删改时;涉及到两个方向的选择
1、是删除还是更新redis缓存
2、是先删除更新缓存;再操作数据库;还是先操作数据库;再删除更新缓存。
下面一一讨论

;1;数据发生变化;删除还是更新redis缓存

更新;数据发生增删改;把缓存的内容 重新用redis的set操作;赋予新值。
删除;在查询时;发现缓存已经不存在;去数据库查询之后;同步到redis缓存。

如何选择;可以使用排除方法;首先讨论更新。
1、redis更新是放在数据库操作的前。
线程1; redis更新 ---------------------------数据库更新
线程2;redis更新-------------------------数据库更新
2、redis更新是放在数据库操作的后。
线程1; 数据库更新 ---------------------------redis更新
线程2;数据库更新-------------------------redis更新
可以看到这样的场景;当线程1和2完成之后;此时缓存和数据库是不一致的。
2、写多读少;上面一直讨论缓存的目的是给读操作使用的;那么每修改一次就写入一次缓存;无疑大大的做无用功。
3、如果缓存是需要计算加工的数据;即查询到数据库值之后;缓存的值需要再做计算;那么每一次修改将很损耗性能。

总结;综合上面三点;删除要比更新的效率和避免数据不一致的效果更好。

;1;数据发生变化;先删除还是先操作数据库

1、 先更新数据库;再删除缓存
2、先删除缓存;再更新数据库
下面一一讨论;
;1;先更新数据库;再删除缓存
①如果更新数据库失败;那么程序捕获异常;之后不进行删除缓存操作。
②如果更新数据库成功;但是删除缓存失败。
针对②可以采用异步操作的办法;把删除失败的key给到队列当中;由线程池来执行失败重试。
或者可以利用canal 监听数据库修改 进而发生删除的操作。

;2;先删除缓存;再更新数据库
这种方式可能存在以下三种异常情况

1、删除缓存失败;这时可以通过程序捕获异常;直接返回结果;不再继续更新数据库;所以不会出现数据不一致的问题
2、删除缓存成功;更新数据库失败。此时不会发生数据不一致现象。
3、下图的场景;两个线程执行完成之后;会导致redis和数据库的不一致。
redis和数据库的一致性问题的解决方案
解决第三种情况可以使用 延时双删的策略;如下图;
redis和数据库的一致性问题的解决方案
这里讨论一下延时双删如何解决第三种异常情况;
1、线程2在查询数据库旧值之后;更新缓存;此时数据不一致;所以需要再次删除。
2、休眠时间;是为了在线程2写入缓存之后;线程1才发生删除缓存;不延时;可能导致线程2还没写入缓存;线程1就完成了删除缓存;那么最终的结果 还是数据不一致。
3、无论如何线程2并利用的是旧数据;这点没办法更改这点容错率还是支持的;毕竟要是发生在删除缓存前一秒还会利用缓存;此时数据还是最新数据;而删除缓存之后的一秒;才会到数据库去查最新数据;这个时间差的代价无论如何一定存在。
伪代码;

public void update(String key, Object data) {
    // 首先删除缓存
    redisCache.delKey(key);
    // 更新数据库
    db.updateData(data);
    // 休眠一段时间;时间依据数据的读取耗费的时间而定
    Thread.sleep(500);
    // 再次删除缓存
    redisCache.delKey(key);
 

总结

1、选择删除缓存 而不是更新
2、如果先修改数据库;再删除缓存;缓存删除成功的机制可以用异步的失败重试机制。
3、如果先删除缓存;再修改数据库;可以使用延时双删的机制。

文章摘录至https://blog.csdn.net/chanmufeng/article/details/122933214

加载全部内容

相关教程
猜你喜欢
用户评论
快盘暂不提供评论功能!