Write Through
这个说法也叫做写穿透,是指当业务方写入数据的时候,只需要写入缓存,缓存会代替业务方去更新数据库。
Write Through读数据的步骤跟Cache Aside是一样的
Write Through就是在写入数据的时候,只写入缓存,缓存会代替我们去更新数据库。但是Write Through没有要求先写数据库还是先写缓存,不过一般也是先写数据库。
其次,Write Through也没有讨论如果缓存中原本没有数据,那么写入数据的时候,要不要更新缓存。一般来说,如果预期写入的数据很快就会读到,那么就会刷新缓存中的数据。
Write Through也有对应的异步变种方案。当然,这些变种也都没有解决缓存一致性的问题。
在刚刚的回答里,提到了写入顺序的问题,那么面试官就可能会追问写入一致性的问题。显然,Write Through也没有解决一致性的问题,你同样可以参考Cache Aside中的分析。
亮点:异步方案
类似的,Write Through也可以考虑异步,也就是写入缓存以后,缓存立刻返回结果。
但是这种模式是有可能丢数据的,也就是当业务代码收到成功响应之后,缓存崩溃了,那么数据其实并没有写入数据库中。
另一个比较可行的变种是同步写到数据库里,但是会异步刷新缓存。
在缓存收到写请求之后,可以直接返回成功响应,然后异步写入数据库和刷新缓存。但是这种方案比较危险,存在数据丢失的风险。
缓存也只可以考虑只写入数据库,然后返回成功响应,后面可以异步刷新缓存。
基本上前者很少用,要用的也是和它很像的Write Back方案。变种二则适合用于缓存写入操作且代价高昂的场景。比如前者提到的,写入大对象或者需要序列化大对象再写入缓存。
Write Back
在这个模式下,当你写入数据的时候,只是写到了缓存,当缓存过期的时候,才会被刷新到数据库。
Write Back模式是指我们在更新数据的时候,只把数据更新到缓存中就返回。后续会有一个组件监听缓存中过期的key,在过期的时候将数据刷新到数据库中。显然,只是监听过期key的话还是有问题,比如关闭缓存的时候还是需要把缓存中的数据全部刷新到数据库里。
但是如果数据还在缓存中的时候,缓存突然崩溃了,那数据就直接丢了。
Write Back有一个硬伤,就是如果缓存突然宕机,那么还没有刷新到数据库的数据就彻底丢失了。这也限制了Write Back模式在现实中的应用。不过要是缓存能够做到高可用,也就不容易崩溃,也可以考虑使用。
到这里还可以进一步刷亮点,深入讨论Write Back和数据一致性的问题,所以可以稍微你可以稍微总结一下。
Write Back 最大的优点是排除数据丢失这一点,它能解决数据一致性的问题。
亮点:能否解决数据一致性问题
这里要分成两种情况讨论,使用本地缓存还是使用Redis这种缓存。你可以肯定的是,如果使用的是本地缓存,那么Write Back也会有不一致的问题,毕竟你的数据缓存在多个节点上。但是如果你使用的是Redis,在不考虑缓存丢失的情况下,你就可以做到数据一致性了。
首先,在使用Redis更新数据的时候业务代码只更新缓存,所以对于业务方来说必然是一致的。也就是说,虽然数据库的数据和缓存的数据不一致,但是对于业务方来说,它只能读写到缓存的数据,对业务方来说,数据是一致的。
这是第一个前提,也就是写操作不会带来不一致的问题。紧接着你要解释读操作。
当业务方读数据的时候,如果缓存没有数据,就要去数据库里面加载。这个时候,就可能会产生不一致的问题。比如数据库中a=3,读出来以后还没写到缓存里,这个时候来了一个写请求,在缓存中写入了a=4。如果这时候读请求回写缓存,就会用数据库里的老数据覆盖新数据。
紧接着补充解决方案。
解决这个问题的思路也很简单,当读请求回写的时候,使用SETNX命令。也就是说,只有当缓存中没有数据的时候,才会回写数据。而如果回写失败了,那么读请求就会再次从缓存里获取数据。
最后你一锤定音,总结一下。
因此 Write Back 除了有数据丢失的问题,在缓存一致性的表现上,比其他模式要好。
如果你觉得说 Write Back 解决了一致性问题有点夸张,你可以说 **Write Back 极大地缓解了数据不一致的问题。