缓存与数据库数据一致性问题?
为什么会出现数据的不一致性?
一般而言,如果一开始缓存是空的话,那么查询某条记录是先查询数据库然后再将这条数据放到缓存中。但如果是更新操作呢?在分布式环境中呢?
在分布式环境中,可能在一个时间点内有多个请求同时操作一个数据,比如一个请求查询ID=1的数据,而另一个请求修改ID=1的数据,那么这个时候就容易造成数据的不一致性了。
场景一:请求1查询ID=1的数据,发现缓存中有这条数据,ok,那我直接返回。而此时请求2正在修改这条数据,并且将数据库更新了,ok,即便你已经更新缓存了,但此时请求1已经返回了,这样造成请求1与后面的请求的数据不一致。
场景2:请求1更新ID=1的数据,那么你是先更新数据库信息呢还是删除缓存的信息?
先删除缓存再更新数据库:请求1进来,首先删除缓存,此时请求1还没有更新数据库又或者更新数据失败了,而此时请求2已经进来,请求2开始查询这条记录,发现缓存中没有,那么它就会去查询数据库,查到放到缓存中并返回了,此时请求1才开始更新数据库,那么是不是又会造成缓存与数据库数据不一致。
先更新数据库再删除缓存:请求1进来先更新数据库,将数据库更新完成了但还没有删除缓存,此时请求2进来查询这条记录,发现缓存中有,那么它直接返回了,请求1再删除缓存,这样就导致请求2查到的数据又与数据库不一致了。
这可咋整呢?其实我们发现都是因为在分布式环境下有多个请求都是并发的才会导致这个问题,一个写请求还没有写完,读请求就过来了。
有没有发现一个问题,为什么是删除缓存而不是更新缓存?
原因很简单,因为在很多时候,在复杂点的缓存场景中,缓存中的数据不仅仅是直接从数据库取出来的值,可能是涉及多张表计算出来的值。
比如:可能更新了某个表的一个字段,然后其对应的缓存,是需要查询另外两个表的数据并进行运算,才能计算出缓存最新的值的。
另外更新缓存的代价其实是很高的。假如每次更新数据库的时候,都将缓存更新一遍,但如果涉及到比较复杂的场景例如频繁的修改一个缓存中的多个表,但问题是,这个缓存是否被频繁的访问?
举个例子,一个缓存涉及的表的字段,在一分钟之内修改20次、100次,那么缓存更新20、100次,但一分钟只被查询了一次。但如果是删除缓存的话,我一分钟删除20、100次,又不用做更新操作,等到你用的时候再去查,这样是不是节省了开支。
如何优化?
那么能否做到当一个请求处理完毕后再进行下一个请求呢?
做串行话,即将读请求和写请求放到一个队列里面去。但这样的问题是大量请求势必会导致系统吞吐量降低,影响性能。
https://www.cnblogs.com/justdojava/p/11212121.html

浙公网安备 33010602011771号