略难的问题,在校招不常见,在社招并且你提及使用了本地缓存之后,差不多就是必问的题目了。
在回答这个问题的时候,在罗列了各种解决方案之后,有两个刷亮点的方向:一个方向就是讨论一些注意事项和细节,另外一个方向就是结合你自己的实践,阐述你在什么场景下用过什么方案。
这个问题问的是,当我要更新本地缓存数据的时候,我怎么更新所有节点上的本地缓存呢?如图:
从实践上说,有很多种做法。
第一种做法:广播。也就是借助 RPC 中的广播功能或者自己手动挨个调用过去,有两种广播方式,如下图:
第二种做法,监听 binlog。当然,前提条件是更新的数据库。一般的架构都是借助 Canal 来进行,有些时候还会在 Canal 后转一个消息队列 Kafka,但是 Kafka 不是必须的。如图:
第三种做法,借助消息队列来通知。如图:
第四种做法,监听 etcd, nacos 等配置中心的变更,而后节点更新本地缓存。这种形态和上一种形态差不多:
第五种,本地缓存框架支持共识算法,例如说 RAFT 之类的算法,那么它们之间自己协调,最终会达成一致:
第六种,本地缓存定时刷新。也就是不管发生了什么,反正到期就刷新。这种方式常见于热点数据中。
这些技巧很多,你随便记住两三个就可以了,毕竟你的面试官也不会那么多种技巧。
此外还有一个问题,即通知节点的时候,通知的内容有两种:
因为本身通知可能重复,所以还要进一步小心幂等问题,即更新缓存的操作应该是幂等的。比如说如果更新缓存是将缓存的值 +1,那么这种就要小心因为重复通知导致多加了。
有一些做法节点是能收到自己发出去的通知的,例如说节点 A 订阅了 Kafka 的消息,而后收到了自己发出来的消息。这不是什么问题,如果能判定出来是自己发的(例如说消息里面带了通知者),那么可以直接忽略;如果不能判定出来,那么就再次刷新缓存。
而更新缓存是一个含糊的说法,可以是删除本地缓存,而后等缓存未命中的时候加载。也可以是直接更新为最新的数据。不管是哪个,都要小心并发更新的问题。
这个问题跟使用本地缓存如何保证数据一致性强相关,但是后者还包含了并发更新、部分失败等问题。