面试题答案
一键面试读写并发下不一致问题分析
- 读操作先于写操作:
- 问题:读操作从缓存中读取到旧数据,而此时写操作已经在数据库中更新了数据。例如,商品库存,读操作获取到旧的库存数量,而写操作已经减少了库存。
- 原因:缓存更新不及时,读操作在缓存更新前执行。
- 写操作先于读操作:
- 问题:写操作更新了数据库,但由于网络延迟等原因,缓存未能及时更新,读操作从缓存中读取到旧数据。比如,用户修改了个人信息,数据库已更新,但缓存中仍是旧信息。
- 原因:缓存更新机制存在延迟或失败。
解决方案及优缺点
- 先更新数据库,再更新缓存:
- 实现:业务逻辑中,先执行数据库的更新操作,成功后再更新缓存。
- 优点:实现相对简单,符合常规逻辑。
- 缺点:在高并发下,如果更新缓存失败,会导致数据不一致。而且在更新数据库和更新缓存之间有短暂时间窗口,可能读到旧缓存数据。
- 先删除缓存,再更新数据库:
- 实现:业务逻辑先删除缓存数据,然后更新数据库。
- 优点:避免了更新缓存失败导致的数据不一致问题,因为后续读操作会重新从数据库加载数据到缓存。
- 缺点:在高并发场景下,可能出现缓存击穿问题。即一个写操作删除缓存后,读操作在数据库更新前执行,会从数据库读取旧数据并重新写入缓存,导致缓存中数据与数据库不一致。
- 先更新数据库,再删除缓存:
- 实现:业务逻辑先更新数据库,成功后删除缓存。
- 优点:这是比较常用的方案,相对平衡。避免了先更新缓存失败的问题,同时相比先删除缓存再更新数据库,减少了缓存击穿的概率,因为数据库已更新,即使读操作先于缓存删除执行,后续缓存删除后读操作也会从数据库获取新数据。
- 缺点:在高并发下,写操作和读操作同时进行时,可能会读到旧的缓存数据,存在短暂的数据不一致窗口。但这个窗口时间较短,而且随着缓存过期机制,数据最终会一致。
- 使用队列或消息中间件:
- 实现:将读写操作发送到队列或消息中间件,由队列按顺序处理,确保读写操作的顺序性。例如,将写操作的更新数据库和删除缓存步骤封装成消息发送到消息队列,消息队列按顺序处理消息。
- 优点:可以有效保证数据一致性,通过顺序处理读写操作,避免了并发带来的不一致问题。
- 缺点:引入了额外的中间件,增加了系统的复杂性和维护成本,同时可能会带来性能损耗,因为消息处理有一定的延迟。
- 缓存双写:
- 实现:在写操作时,同时更新主缓存和备用缓存,读操作先从主缓存读取,若读不到再从备用缓存读取,备用缓存数据定期同步到主缓存。
- 优点:可以在一定程度上保证数据一致性,即使主缓存更新失败,备用缓存可能有最新数据。
- 缺点:增加了缓存维护成本,需要管理两个缓存,并且同步备用缓存到主缓存也存在一定的复杂性和延迟。