MST
星途 面试题库

面试题:缓存设计中复杂业务场景下缓存层与业务层深度解耦与协同优化

在一个具有复杂业务逻辑的金融系统中,涉及多种业务流程和数据交互,且对数据的实时性和准确性要求极高。请描述你将如何设计缓存层与业务层,以实现深度解耦与高效协同,同时还要考虑缓存的更新策略、数据一致性保证以及故障恢复机制等方面,给出完整且详细的设计方案。
33.4万 热度难度
后端开发缓存设计

知识考点

AI 面试

面试题答案

一键面试

缓存层设计

  1. 缓存选型:鉴于金融系统对数据实时性和准确性要求高,选用 Redis 作为缓存。Redis 支持多种数据结构(如字符串、哈希表等),读写性能高,适合处理高频读写场景,且具备丰富的原子操作指令,有助于确保数据一致性。
  2. 数据存储结构
    • 对于业务流程中频繁查询且数据量较小的基础配置信息(如利率、手续费率等),使用 Redis 的字符串结构存储。例如,以配置项名称为键,具体数值为值。
    • 对于涉及用户账户等关联关系较多的数据,采用 Redis 的哈希表结构。以用户 ID 为键,哈希表的字段存储账户相关的各个属性(如余额、交易记录等)。
  3. 缓存分区:为提高缓存的并发处理能力和可用性,采用一致性哈希算法进行缓存分区。将缓存数据分布到多个 Redis 实例上,每个实例负责一部分数据的存储和读取。这样当某个实例出现故障时,只会影响部分数据的缓存,其他实例仍能正常工作。

业务层设计

  1. 分层架构:业务层采用分层架构,分为表现层、应用层和领域层。
    • 表现层:负责接收用户请求并返回响应数据,与前端进行交互。将请求参数进行初步验证和转换后传递给应用层。
    • 应用层:协调领域层的业务逻辑执行,根据业务需求调用不同的领域服务。同时,负责与缓存层进行交互,处理缓存的读取和更新操作。
    • 领域层:包含核心业务逻辑,封装业务规则和实体对象。领域层专注于业务本身,不依赖于外部技术框架,提高代码的可维护性和复用性。
  2. 依赖注入:通过依赖注入的方式,将缓存层的操作接口注入到业务层的相关组件中。这样业务层与缓存层之间通过接口进行交互,实现解耦。例如,在应用层的服务类构造函数中传入缓存操作接口的实现类,使得业务层无需关心缓存层的具体实现细节。

缓存更新策略

  1. 读写穿透策略
    • 读操作:业务层首先尝试从缓存中读取数据。如果缓存命中,直接返回数据;如果缓存未命中,从数据库读取数据,然后将数据写入缓存,并返回给业务层。
    • 写操作:业务层在更新数据库数据的同时,更新缓存数据。为确保数据一致性,使用事务机制,将数据库更新和缓存更新作为一个事务进行处理。如果其中任何一个操作失败,整个事务回滚。
  2. 异步更新策略:对于一些对实时性要求稍低的业务数据更新,可以采用异步更新策略。当业务层更新数据库数据后,发送一条消息到消息队列(如 Kafka)。缓存层订阅该消息队列,接收到消息后进行缓存数据的更新。这种方式可以减少对业务层的响应时间影响,但需要注意消息处理的可靠性和数据一致性。

数据一致性保证

  1. 缓存版本控制:为每个缓存数据设置版本号。当数据库数据发生变化时,更新数据库的同时更新对应的缓存版本号。业务层在读取缓存数据时,不仅读取数据本身,还读取版本号。如果发现版本号与预期不符,说明缓存数据可能已过期,重新从数据库读取数据并更新缓存。
  2. 双写一致性方案:在读写穿透策略基础上,采用“先更新数据库,再更新缓存,然后延迟删除缓存”的方案。当更新数据库成功后,立即更新缓存,然后设置一个短时间的延迟(如 100ms),在延迟时间后删除缓存。这样可以避免在高并发场景下,先删除缓存后更新数据库导致的缓存与数据库数据不一致问题。

故障恢复机制

  1. 缓存数据持久化:Redis 提供了 RDB(Redis Database Backup)和 AOF(Append - Only File)两种持久化方式。启用 AOF 持久化,将写操作以追加日志的形式记录下来。当 Redis 发生故障重启后,可以通过重放 AOF 日志来恢复缓存数据,确保数据的完整性。
  2. 故障监控与自动切换:使用 Redis Sentinel 或 Redis Cluster 实现故障监控和自动切换。Sentinel 可以监控 Redis 主从节点的运行状态,当主节点发生故障时,自动将从节点提升为主节点,并通知其他节点进行相应的配置更新。Redis Cluster 则是一种分布式部署方案,具有自动故障检测和故障转移功能,确保缓存服务的高可用性。
  3. 业务层重试机制:在业务层,当与缓存层交互出现故障(如缓存连接超时、读取失败等)时,采用重试机制。设置合理的重试次数(如 3 次)和重试间隔时间(如每次间隔 100ms)。如果重试多次仍失败,则记录详细的错误日志,并返回适当的错误信息给用户,同时可以考虑从数据库直接读取数据以满足业务需求,保证业务的基本可用性。