MST

星途 面试题库

面试题:缓存设计之专家难度:分布式系统下的缓存一致性解决方案设计

假设你正在设计一个大型分布式电商系统,系统中涉及商品信息、库存等数据的缓存,为确保缓存一致性,防止出现超卖等问题,设计一套完整的缓存一致性解决方案,并详细说明方案中如何应对网络分区、节点故障等异常情况。
28.2万 热度难度
后端开发缓存设计

知识考点

AI 面试

面试题答案

一键面试

缓存一致性解决方案

  1. 读写策略

    • 写策略
      • 采用“先更新数据库,再删除缓存”的策略。当商品库存发生变化时,首先更新数据库中的库存数据。这是因为数据库是数据的持久化存储,保证数据的最终一致性。更新成功后,立即删除对应的缓存数据。例如,在一个商品库存减少的场景中,先在数据库中将库存字段的值减1,然后删除缓存中该商品的库存信息。这样当下次读取库存时,缓存中不存在该数据,会从数据库加载最新数据并重新写入缓存。
      • 为了防止在高并发场景下,“先更新数据库,再删除缓存”过程中,缓存还未删除,其他读请求读到旧缓存数据的问题,可以使用分布式锁。在更新数据库和删除缓存操作前后加锁,确保同一时间只有一个线程进行更新和缓存删除操作。
    • 读策略
      • 先从缓存读取数据,如果缓存命中,直接返回数据。例如,当查询商品库存时,先在缓存中查找该商品库存信息,如果找到则直接返回给调用方。
      • 如果缓存未命中,则从数据库读取数据,返回给调用方,并将数据写入缓存。如在缓存中未找到商品库存信息,就从数据库中查询,查询到后将库存数据返回给调用方,同时将该库存数据写入缓存,以便后续请求可以直接从缓存获取。
  2. 缓存架构

    • 使用分布式缓存,如Redis集群。Redis集群具有高可用性和可扩展性。它通过将数据分布在多个节点上,提高了系统的读写性能和存储容量。例如,一个大型电商系统可以部署多个Redis节点组成集群,不同商品的缓存数据分布在不同节点上,通过一致性哈希算法将数据映射到具体节点。

应对异常情况

  1. 网络分区
    • 读操作:在网络分区情况下,如果读请求所在的分区与缓存集群的部分节点网络隔离。读请求首先尝试从本地缓存(如果有本地缓存机制)读取数据。若本地缓存未命中,对于可以接受一定数据不一致性的场景,可以返回旧的缓存数据(前提是设置了合理的缓存过期时间)。若必须获取最新数据,读请求可以等待网络恢复或者尝试通过其他网络路径(如备用网络通道)连接到缓存集群的其他正常节点读取数据。
    • 写操作:当发生网络分区时,写请求所在分区与缓存集群部分节点隔离。写请求依然先更新数据库,确保数据持久化。对于缓存操作,若写请求所在分区内有缓存节点副本(如果采用了缓存数据多副本机制),则更新本分区内的缓存副本数据。同时,记录下本次缓存更新操作日志。当网络恢复后,根据日志将缓存更新同步到其他分区的缓存节点。
  2. 节点故障
    • 缓存节点故障:对于Redis集群,它本身具有一定的节点故障自动恢复机制。当某个Redis节点发生故障时,集群会自动将该节点的数据迁移到其他正常节点(通过集群的重新分片机制)。为了提高系统的健壮性,可以设置多个从节点,主节点故障时,从节点可以晋升为主节点继续提供服务。在应用层面,当发现某个缓存节点故障导致缓存读取失败时,应用程序可以进行重试,尝试从其他正常节点获取数据。
    • 数据库节点故障:如果数据库节点发生故障,系统应切换到备用数据库节点。在故障期间,对于写操作,若数据库采用的是主从架构且主库故障,写请求可以先发送到从库(前提是从库支持写操作,即采用了双活或多活架构),同时记录写操作日志。待主库恢复后,根据日志将数据同步到主库。对于读操作,优先从缓存读取数据,缓存未命中时,从备用数据库节点读取数据。