> 文档中心 > 关于缓存一致性的思考?

关于缓存一致性的思考?

在应用程序中通常应用层和数据库层是分开的,我们几乎所有的应用数据都来自于数据库,数据库同时提供的服务。在现代应用体系,微服务化将应用程序模块细分,同时软件设计中也提供了读写分离的概念。

  1. 为什么需要缓存层?

通常数据库服务器使用的物理存储为磁盘形式,受限于硬件的性能瓶颈,导致读写速度达不到产品的需求,并且会导致存储服务器的IO过高,影响写入的性能。同时,在SQL执行的过程中因此,我们在两者之间加入了缓存层,使用内存作为少量数据的临时存储空间以提高的效率。

  1. 缓存层的工作原理?

缓存层实际上存储的是应用程序执行的查询结果,是以查询条件为key,以结果为value的键值对,存放在String型数据中。因此缓存层存放的仅仅只是某一条SQL语句的执行结果,它解决的是相同SQL语句的查询压力问题。将相通的SQL语句的查询转移到redis服务器上,降低对数据库服务器的查询次数。

  1. 缓存层的弊端?

由上一条可知,缓存中存储的只是某一条SQL语句的执行结果,因此保存的数据是经过筛选后的结果,当我们对这部分数据做了修改之后,缓存层是无法主动感知的,因此造成查询到的结果和数据库的实际存储不匹配。因此当我们不做必要处理时,只有当redis中的数据无法查询后,才会重新从数据库中读取数据并写入到redis内存中。

  1. 解决数据不一致的思路?

当我们需要写操作时,需要对redis中的数据进行必要处理,但是由于redis中的数据是通过SQL语句分析筛选而来,因此无法通过直接修改缓存达到和数据库一致的目标。因此只能通过删除相关表的所有缓存数据达到更新的目的,等待新的查询结果重新写入缓存层。

  1. 带来的问题?

删除相关表缓存带来的缓存雪崩
数据库写入速度较慢导致在写入的过程中在缓存中写入旧的查询结果,导致双写不一致,数据库更新完成后,缓存中还是旧的数据

  1. 如何解决新的问题?

    对数据库的更新操作涉及到数据库事务问题,只有当数据库事务完成,数据才算写入到实际的数据库层。此时才会涉及到更新缓存的问题,当事务的执行时间较短时,我们可以通过数据库事务的执行成功回调方式更新缓存中的数据,避免删除大量相关缓存时带来的缓存雪崩。同时为了避免删除缓存失败导致的旧数据查询问题,使用消息队列对删除结果做重试操作,以保证缓存中的数据已被删除。同时由于是逐个键删除造成缓存雪崩的概率较低。在并发环境下,A线程寻到数据因此不会写入操作,B线程由于删除操作后查询不到数据会写入新的数据,此时会造成两次查询结果不一致的情况,但由于两次查询发生的时间发生在事务完成的前后,因此数据业务范畴,影响较小。