这里我讲的是缓存和数据库,以redis和mysql举例,实际上缓存包括不限于浏览器缓存、redis、memcache、本地缓存guava等等,数据库也有很多种,这里我们仅仅以较常见的redis和mysql举例。
一,缓存与数据库的查询、写入
1,双写一致性
在以数据库作为查询终点的项目里,一般在查询的时候,使用被动更新
,即查询不到数据,从数据库获取数据,将其更新到缓存中。而在进行写操作的时候,如果只是依靠缓存的过期,会存在比较大的一致性问题,因此需要使用主动更新
,即需要主动对缓存进行更新。而主动更新,存在双写一致性
问题,下面是4种主动更新的方案。
更新缓存、更新数据库
基本上更新缓存的方案都存在一致性的问题,虽然不一致的原因不一样,但是结果都是数据一致性问题比较严重。比如这个先更新缓存,再更新数据库。如果更新数据库失败,直到数据库回滚后,将缓存数据更新为旧值之前,缓存中被更新的值都存在一致性问题,数据库写操作和回滚比较耗时,这期间缓存数据一直是不一致的,因此这个方案一般不采用。
更新数据库、更新缓存
这个方案的一致性问题是因为多线程导致的。假设a线程更新数据库后,还没有更新缓存,此时b线程更新了数据库与缓存,最后a线程更新了缓存。b线程后更新的数据库,但是最后缓存里的数据是先更新的a线程的数据,如果后面再有新的线程来查询,并且读多写少,那么数据会在相当一段时间内存在一致性问题。