赞
踩
一般来说生产环境中,我们为了保证数据响应的速度,会将数据保存在数据库中,但是会将部分数据(一般是最近被访问的数据)备份在缓存中。用来避免频繁的IO导致的性能下降。
而现在我们大多使用读写分离的行为,既然数据被保存在了两个地方,在数据更新的时候就可能导致数据的不一致。如何保证数据库和缓存数据的一致。
目前关于简单保证缓存一致性的方案主要有下面几个
使用这种方式,整个流程被分为了下面样子
这样操作可能出现的情况:
使用这种方式的考虑在于,每次修改数据就去更新缓存的数据,但是此时缓存中的数据可能并没有被使用。而删除缓存可以保证它到需要被使用的时候再重新计算。这种操作就是数据的懒加载的方式。
使用这种方式,可以保证在数据更新成功,去更新缓存失败的时候,缓存一段时间后因为超时而去同步数据库中的数据,从而完成数据的最终一致性。在简单的处理方式中国,这一种应该是最接近问题解决的方案。但是这种方案的问题在于在缓存过期之前,缓存和数据库中数据不一致,会导致短时间的脏数据。
一种方案是将每个操作作为一个任务压入一个共享的队列中,使用队列来保证先后顺序。
写入数据的时候大概流程
整个流程可以归纳为下面的过程
这个流程实际上可以发现,解决方案其实是把读写操作作为了一个串行的操作。这样操作可以保证缓存和数据库中数据的强一致。
但是存在几个问题。
优化的策略主要针对效率和超时
另外一种方案通过为数据设置状态来标识数据此时是否可用。整个流程可以描述为下面内容。
写数据
整个流程总结下来是如下内容
读数据
整个流程总结下来是如下内容
为数据设置状态的处理方案,其实和Redis分布式锁的思想是一致的。通过获取数据的锁来判断数据此时是否可以被更新或者读取。
使用类似读写锁的操作来保证并行读和串行读写。
这种情况已经尽量满足一致性的要求,当然这里面还有一些东西需要注意。
缓存清理的时机
写数据的时候,在设置了数据状态之后就进行缓存清理工作。假如此时缓存清理成功后,在更新数据失败。此时会导致缓存数据为空,然后不得不去数据库再次去获取旧的内容。
而假如我们更新时候将缓存清理推后到数据更新之后,可以保证在数据更新失败情况下缓存无需进行额外操作。但此时会面临两个问题,在更新数据和清理缓存中短暂时间内“脏数据”的存在,其次在更新数据成功而清理缓存失败的情况下导致数据库中数据和缓存中数据的不一致,在没有设置缓存时间的情况下,缓存无法自动修正。
更新缓存的操作
当一个数据被更新的时候,针对此数据读取会被阻塞起来,多个请求可能都在等待请求数据。当次数据更新完成后,
为了避免多个请求重复的想数据库请求此数据。可以在获取到此数据的锁定状态后,再次向缓存中验证数据是否存在。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。