什么情况下会出现数据库和缓存不一致的问题?
在非并发场景下,由于缓存操作和数据库操作存在时间差且无法保证原子性,数据不一致问题很容易理解。这两个操作可能一个成功一个失败,因此必然会出现不一致的情况。
在并发场景中,当两个线程同时执行"先写数据库后更新缓存"的操作时,可能会出现以下时序问题:
- 线程A:写数据库更新为20
- 线程B:写数据库更新为10
- 线程B:写缓存更新为10
- 线程A:写缓存更新为20(最终缓存与数据库不一致)
同样地,在"先更新缓存后写数据库"的场景中也会出现类似问题:
- 线程A:写缓存更新为20
- 线程B:写缓存更新为10
- 线程B:写数据库更新为10
- 线程A:写数据库更新为20(数据不一致)
此外,读写并发场景也容易被忽视。使用缓存时,读取线程的执行流程如下:
- 查询缓存,命中则直接返回
- 未命中则查询数据库
- 将数据库结果更新到缓存
虽然读取线程不会修改数据库,但会更新缓存。在某些特殊并发情况下,可能导致数据不一致:
- 读取线程查询缓存未命中
- 读取线程从数据库获取结果10
- 写入线程更新数据库和缓存为20
- 读取线程将旧值10写入缓存(导致数据不一致)
这种情况发生的概率较低,因为读取操作通常很快完成(数据库+缓存查询约十几毫秒)。在此期间恰好遇到耗时写入操作的概率较小。但根据墨菲定律,只要可能发生就一定会发生,因此仍需重视这个问题。