面试专栏:缓存数据库一致性

28 篇文章 0 订阅
本文讨论了如何在火车票业务中通过缓存和数据库一致性解决方案,如使用Binlog和Canal确保数据同步。介绍了两种缓存同步模型,包括同步更新和Binlog模式,并分析了支付前后扣减库存的不同策略及其优缺点。
摘要由CSDN通过智能技术生成

业务背景

为了满足用户对一趟列车不同站点不同座位类型的余量查询需求,我们采取了一种优化方案。我们将这些余量信息存储在缓存中,以便用户可以快速查询

然而,在用户创建订单并完成支付时,我们需要同时从数据库和缓存中扣减相应的列车站点余票。这种设计不仅提高了查询效率,也保证了数据的一致性,确保订单操作的准确性。

在这个业务场景中的缓存与数据库一致性如何保证?

项目实战

通过数据库缓存一致性文章我们了解到,适合咱们这个车票余量缓存的方案是通过 Binlog 异步更新列车缓存,详细逻辑查看上文。

如何保证缓存一致性

我们采用了一种确保缓存和数据库一致性的方案,使用 Canal 监听 Binlog 模式。该方案将数据库的数据变更通过 Canal 转发给消息队列的特定 Topic。客户端应用程序可以监听该消息队列的 Topic,以保持缓存与数据库的一致性

时序图如下所示:

这套逻辑在应用层面上非常严谨,但存在一个问题,即复杂性较高。如果大家想进行测试,需要启动 Canal 监听并结合消息队列进行测试。

为了解决这个问题,我在代码中添加了两种缓存同步模型。其中一种是在业务代码中同步地操作缓存扣减,这种方案比较简单,可以帮助大家快速熟悉业务流程。但是,这种方案在中间或快结束时如果出现异常,可能会导致缓存数据出现问题。

方案具体体现在购票抽象方法 AbstractTrainPurchaseTicketTemplate#executeResp 中添加了条件判断,如果是非 binlog 模式,也就是 ticket.availability.cache-update.type 不等于 binlog,就按照同步更新缓存模式进行。

另一种缓存同步模型被称为 Binlog 模式,它需要在配置文件中添加相关配置并启动 Canal 中间件才能启用。

为什么订阅 Canal 的消费者不用线程池?

目前我们的方案是通过一个 RocketMQ Topic 消费 Canal 传递的 Binlog 数据变更事件。为了提高消费速度,我们可以考虑在客户端消费时增加一个线程池。此外,在消息积压情况下,我们可以利用 Hippo4j 动态调整线程池大小来进一步增加消费速度。

然而,需要注意的是,使用线程池消费消息会使得投递线程池的成功与消息消费成功绑定。如果消费过程中发生失败,我们无法再利用 RocketMQ 的消费失败重试逻辑。尽管我们可以通过其他技术方案实现重试消费逻辑,但这会增加方案的复杂性和不确定性。相比之下,直接使用 RocketMQ 方案更加简单。

因此,我们最终选择将 RocketMQ 底层线程池的线程数参数适当增大,以提高消费速度。此外,Hippo4j 可以操作 RocketMQ 底层线程池,在消息积压时,通过动态调整线程池参数来解决积压问题。

为什么扣减数据库需要扣减沿途车站,而缓存扣减不需要?

由于操作数据库时更改了出发站点和到达站点之间的沿途站点,导致对应的沿途车站座位数据的 Binlog 会被投递到 RocketMQ 队列中。应用客户端将完全消费这些 Binlog,因此在扣减缓存时无需再对沿途站点进行扣减操作。

为什么创建订单扣减库存而不是支付后扣减库存?

在我进行了真实实验后发现,在 12306 购买车票时,购买成功后几分钟乃至十几分钟内余票数量并不会减少。

在设计过程中,我主要考虑了两种库存扣减方案:下单扣减库存和支付扣减库存。

1/ 下单扣减库存:

  1. 操作时机:库存在下单时就进行扣减,即在用户下单时就减少库存。
  2. 优势:
  3. 立即锁定库存:下单扣减库存可以立即锁定列车站点的库存,避免其他用户同时购买同一列车车站导致库存不足的问题。
  4. 简化流程:不需要等待支付完成才进行库存扣减,简化了流程。
  5. 劣势:
  6. 库存占用:下单后,如果用户不支付,库存将被长时间占用,可能导致其他用户无法购买该列车站点座位。
  7. 订单超时问题:如果用户下单后长时间不支付,库存将一直被占用,影响其他用户购买。

2/ 支付扣减库存:

  1. 操作时机:库存在支付完成时才进行扣减,即在用户支付成功后再减少库存。
  2. 优势:
  3. 避免库存占用:只有支付成功的订单才会减少库存,避免了长时间占用库存的问题。
  4. 提高订单完成率:只有支付完成的订单才会扣减库存,避免了因用户不支付而导致库存被占用的情况。
  5. 劣势:
  6. 竞争情况:如果多个用户同时下单购买同一商品,可能出现竞争情况,导致库存不足。
  7. 需要处理超时问题:需要考虑订单支付超时的情况,如果超时未支付,需要释放相应的库存。

从实际场景考虑,当用户购买列车车票时,他们的目的是为了支付购买成功。如果用户已经进入支付流程,却被告知库存已售罄,这将给用户带来非常糟糕的体验。

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nathaniel333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值