插件窝 干货文章 并发请求下的数据库锁:先删缓存还是先更新数据库?

并发请求下的数据库锁:先删缓存还是先更新数据库?

缓存 删除 数据库 更新 522    来源:    2025-03-31

并发请求下的数据库锁策略分析

在处理并发请求时,数据库与缓存的一致性问题是一个经典挑战。关于"先删缓存还是先更新数据库"的问题,我将从多个角度进行分析。

两种策略对比

1. 先删除缓存,再更新数据库 (Cache-Aside Pattern)

流程: 1. 删除缓存 2. 更新数据库

潜在问题: - 在删除缓存后、数据库更新完成前,如果有读请求,会从数据库读取旧数据并重新填充缓存,导致缓存"脏数据"

2. 先更新数据库,再删除缓存

流程: 1. 更新数据库 2. 删除缓存

优势: - 减少了缓存与数据库不一致的时间窗口 - 即使删除缓存失败,下次读取也会从数据库获取最新数据并重建缓存

推荐解决方案

最佳实践:先更新数据库,再删除缓存 + 重试机制

  1. 基本流程:

    • 更新数据库
    • 删除缓存
    • 如果删除失败,通过消息队列或后台任务重试删除操作
  2. 增强方案:

    • 引入双删策略:更新前删除一次缓存,更新后再删除一次
    • 设置缓存过期时间作为兜底方案
    • 使用分布式锁防止并发更新问题

伪代码示例

public void updateData(Data newData) {
    // 获取分布式锁
    Lock lock = distributedLock.acquireLock("data_" + newData.id);
    try {
        // 第一次删除缓存
        cache.delete("data_" + newData.id);

        // 更新数据库
        database.update(newData);

        // 第二次删除缓存
        cache.delete("data_" + newData.id);

        // 延迟队列确保最终一致性
        delayQueue.add(new CacheDeleteTask("data_" + newData.id));
    } finally {
        lock.release();
    }
}

不同场景下的选择

  1. 读多写少场景:先更新数据库再删除缓存
  2. 写多读少场景:可考虑直接更新缓存(Write-Through模式)
  3. 强一致性要求:使用分布式事务或2PC协议

总结

在大多数情况下,"先更新数据库,再删除缓存"是更优的选择,配合适当的重试机制和过期策略,可以在性能与一致性之间取得良好平衡。关键是要根据业务特点选择最适合的策略,并做好异常处理。