 从图中可以看到,Tomcat 上运行的应用,无论是新增(Insert 操作)、修改(Update 操作)、还是删除(Delete 操作)数据 X,都会直接在数据库中增改删。当然,如果应用执行的是修改或删除操作,还会删除缓存的数据 X。
1、新增数据
如果是新增数据,数据会直接写到数据库中,不用对缓存做任何操作,此时,缓存中本身就没有新增据,而数据库中是最新值,此时,缓存和数据库的数据是一致的。
2、删改数据
如果发生删改操作,应用既要更新数据库,也要在缓存中删除数据。这两个操作如果无法保证原子性。
2.1、不考虑并发性
先删除缓存值后更新数据库值 :数据库更新失败,导致请求再次访问缓存时,发现缓存缺失,在读数据库时,从数据库中读到的是旧值  先更新数据库,后删除缓存值 :缓存删除失败,导致请求再次访问缓存时,发现缓存命中,并从缓存中读到旧值。 
2.1.1、如何解决缓存数据不一致
重试机制 :借助消息队列,可以把要删除的缓存值或者是要更新的数据库值暂存到消息队列中(例如使用Kafka 消息队列)。当应用没有能够成功地删除缓存值或者是更新数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或更新。缓存操作成功后,删除消息队列,防止重复消费导致一致性问题 
2.2、高并发场景都成功
2.2.1 先删除缓存,再更新数据库
假设线程 A 删除缓存值后,还没有来得及更新数据库(比如说有网络迟),线程 B 就开始读取数据了,那么这个时候,线程 B 会发现缓存缺失,就只能去数据库读取。这会带来两个问题:
- 线程 B 读取到了旧值;
- 线程 B 是在缓存缺失的情况下读取的数据库,所以,它还会把旧值写入缓存,这可能会导致其他线程从缓存中读到旧值。
等到线程 B 从数据库读取完数据、更新了缓存后,线程 A 才开始更新数据库,此时,缓存中的数据是旧值,而数据库中的是最新值,两者就不一致了。 
2.2.2、如何解决缓存数据不一致:延迟双删
延迟双删 :在线程 A 更新完数据库值以后,我们可以让它先 sleep 一小段时间,再进行一次缓存删除操作。
要加上 sleep 的这段时间,就是为了让线程 B 能够先从数据库读取数据,再把缺失的数据写入缓存,然后,线程 A 再进行删除。所以,线程 A sleep 的时间,就需要大于线程 B 读取数据再写入缓存的时间。
伪代码
redis.delKey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)
2.2.3 先更新数据库值,再删除缓存值
如果线程 A 删除了数据库中的值,但还没来得及删除缓存值,线程 B 就开始读取数据了,那么此时,线程 B 查询缓存时,发现缓存命中,就会直接从缓存中读取旧值。不过,在这种情况下,如果其他线程并发读缓存的请求不多,那么,就不会有很多请求读取到旧值。而且,线程 A 一般也会很快删除缓存值,这样一来,其他线程再次读取时,就会发生缓存缺失,进而从数据库中读取最新值。所以,这种情况对业务的影响较小。 
3、总结

|