先更新数据库,再删除缓存,如果删除缓存失败了,会导致数据库中是新数据,缓存中是旧数据,数据就出现了不一致。一般普通的解决方式有下面两个:
先删除缓存,再更新数据库。如果数据库更新失败了,那么数据库中是旧数据,缓存中是空的,那么数据不会不一致。读的时候缓存没有,所以去读了数据库中的旧数据,然后更新到缓存中。
延时双删,先更新数据库,再删除缓存,5s之后再执行一次删除操作。
public void set(key, value) {putToDb(key, value);deleteFromRedis(key);// ... a few seconds laterdeleteFromRedis(key);
}
有一个请求过来对数据进行变更操作,先删除缓存,然后修改数据库,数据库数据没修改完之前又过来一个请求,去读缓存,发现缓存空了,然后查询数据库,查到了修改前的旧数据,放到了缓存中,然后第一个请求完成了对数据库的修改,此时就造成数据库和缓存中的数据不一样的情况。
分析:数据并发进行读写的时候才可能出现这种问题,如果并发量很低,特别是读并发,每天访问量就1万次,很少的情况下会出现这种不一致的场景。如果每天是上亿的流量,每秒并发读是几万,每秒只要有数据更新的请求,就可能会出现数据库+缓存不一致的情况。
解决方案:更新数据的时候根据数据的唯一标识,将缓存更新的请求发送到一个jvm内存队列中,然后同步等待缓存更新完成。一个数据变更的操作,先删除