您的位置:首页 > 文旅 > 旅游 > 济南网络优化推广公司哪家好_中铁招标在哪个平台_厦门seo小谢_网站cms

济南网络优化推广公司哪家好_中铁招标在哪个平台_厦门seo小谢_网站cms

2024/12/23 9:20:46 来源:https://blog.csdn.net/gendlee1991/article/details/142713328  浏览:    关键词:济南网络优化推广公司哪家好_中铁招标在哪个平台_厦门seo小谢_网站cms
济南网络优化推广公司哪家好_中铁招标在哪个平台_厦门seo小谢_网站cms

在很多高并发的场景如秒杀系统,QPS会瞬时暴增,如果采用直接读写数据库(如MySQL)的方式,很可能会将数据库打垮。因此这种场景需要引入Redis做缓存,应对高并发的访问。但同时也会引入新的风险,最常见的就是缓存与数据库的一致性问题。下面我们来看一下一些常见的方案。

1.Cache Aside(懒加载)模式

在这里插入图片描述

这是最常用的缓存模式之一。在这个模式下,数据更新的主流程发生在数据库中,缓存会根据需要来更新或失效。

流程

  • 查询时,应用首先查询缓存,如果缓存中有数据(缓存命中),则直接返回缓存数据;如果缓存没有数据(缓存未命中),则查询数据库,得到数据后返回并更新缓存。
  • 更新时,应用首先更新数据库,然后将对应的缓存删除或更新(通常删除缓存让下一次查询时重新加载)。

优点

  • 数据一致性较好,因为写操作直接作用在数据库,缓存仅在需要时更新。
  • 缓存可以有效减少数据库的压力。

缺点

  • 第一次查询时,如果缓存中没有数据,会引发数据库查询,可能导致缓存未命中的延迟问题。
  • 如果删除缓存失败,可能会导致缓存与数据库数据不一致。

在这里插入图片描述

2.同步更新模式(Write Through)

在这里插入图片描述

在这个策略下,每次对数据库进行写操作时,缓存会同步更新,也就是写缓存和同步数据库是原子操作,其中一步失败均认为写入失败。

流程

  • 写入时,应用首先将数据写入缓存,然后通过缓存同步到数据库。
  • 查询时,直接从缓存中读取数据。

优点

  • 查询时性能更高,因为数据总是直接从缓存中获取。
  • 数据一致性较好,因为每次写操作都会同时更新缓存和数据库。

缺点

  • 每次写操作都要更新缓存和数据库,写入性能可能较低。
  • 如果数据库写入失败(但是写入者没有感知到,或原子性策略不成功),缓存和数据库可能出现不一致的情况。

3.异步更新模式(Write Behind)

在这里插入图片描述

这个模式下,写操作只作用于缓存,缓存中的数据异步写入到数据库中。

流程

  • 写入时,应用先将数据写入缓存,然后异步地将数据写入数据库。
  • 查询时,直接从缓存中读取数据。

优点

  • 写操作性能较高,因为不需要立即更新数据库。
  • 查询效率也高,因为数据总是从缓存中获取。

缺点

  • 存在数据一致性风险,因为数据可能还未同步到数据库就被读取。
  • 如果系统崩溃,可能会导致数据丢失。

在这里插入图片描述

同步更新和 异步更新模式的关键区别:

同步更新模式

  • 强一致性:只有当缓存和数据库都成功写入时,才认为写入操作成功。
  • 失败处理:如果任一写入失败,整个操作会被视为失败,通常需要进行错误处理或重试。
  • 保证数据一致性:确保数据在缓存和数据库中始终保持一致性。

异步更新模式

  • 弱一致性:只要缓存写入成功,操作就被视为成功,即使数据库写入失败。
  • 异步处理:数据库的写入在后台进行,可能导致短时间内的数据不一致。
  • 性能优先:提升了写入性能,适合对实时性要求不高的场景。

这种设计选择取决于具体的业务需求和对一致性的要求。

4.提前刷新模式(Refresh Ahead)

在这里插入图片描述

Refresh Ahead 主要是针对读场景的优化策略,其核心目的是在数据即将过期时提前刷新缓存,以提高查询性能。在写入操作方面,通常仍然是直接写入数据库。

  • 读场景:通过预先刷新,确保缓存中的数据在高频访问时始终可用。
  • 写场景:依赖于数据库的更新,可能会使用其他策略(如 Write Through 或 Write Behind)来处理缓存和数据库之间的一致性。

写入流程

  1. 直接写数据库:当应用需要更新数据时,首先将数据写入数据库。
  2. 更新缓存(可选):可以选择立即更新缓存(如 Write Through),或在后台刷新(如 Write Behind)。
  3. 缓存刷新:在 Refresh Ahead 策略下,缓存会在接近过期时被异步刷新,以确保数据的可用性。

优点

  • 查询时减少缓存未命中的概率,避免查询时去读取数据库,提高系统性能。
  • 对频繁访问的数据非常有效。

缺点

  • 如果频繁刷新但实际查询量不大,可能会带来不必要的开销。
  • 可能会引发数据不一致,特别是在缓存刷新期间,数据库中的数据发生了变化。

以上是非常常用的一Redis缓存更新方式,我们看到除了同步更新模式的一致性更好之外,其他的都存在明显的数据一致性问题。那么有没有其他的尽量保证一致性的方案呢?答案是有的。

5.延时双删

在这里插入图片描述

在更新数据时,应用在删除缓存和更新数据库之间引入延迟,执行两次缓存删除。

流程

  1. 更新数据库。
  2. 删除缓存。
  3. 等待一定时间(例如几毫秒)。
  4. 再次删除缓存(即使它已经被更新)。

优点

  • 大幅降低了缓存数据未同步到数据库时的读取不一致性。
  • 对于高并发的场景,双重删除可以显著减少缓存不一致的机会。

缺点

  • 增加了写操作的延迟。
  • 需要合理控制延迟时间,以防止引入过多的延迟或复杂性。

6.分布式锁

在执行更新操作时,通过分布式锁来确保在同一时间只有一个实例能对数据进行更新。

流程

  1. 获取分布式锁。
  2. 更新数据库。
  3. 更新或删除缓存。
  4. 释放锁。

优点

  • 保证在高并发场景下数据一致性。
  • 避免多个实例同时对同一数据进行写入,导致数据冲突。

缺点

  • 引入了额外的复杂性和性能开销。
  • 锁的管理不当可能导致死锁或性能瓶颈。

7.事件驱动架构

时间驱动架构如下:

在这里插入图片描述

使用消息队列或事件总线,在数据库更新时触发事件,异步地更新缓存。

在这里插入图片描述

流程

  1. 更新数据库。
  2. 发布数据更新事件到消息队列。
  3. 监听消息的缓存更新服务消费事件,并更新缓存。

优点

  • 通过异步处理降低了数据库写入的延迟。
  • 系统扩展性好,能够处理高并发情况。

缺点

  • 实现复杂,需处理事件丢失或重复消费的情况。
  • 事件消费延迟可能导致短期内数据不一致。

8.版本号控制

为每个缓存数据增加版本号,每次更新数据时,检查版本号来决定是否更新缓存。

在这里插入图片描述

流程

  1. 查询当前数据版本。
  2. 更新数据库时,版本号加1。
  3. 如果缓存中存储的版本号与数据库不一致,则更新缓存。

优点

  • 通过版本号控制,可以有效降低缓存不一致的问题。
  • 适合高并发场景,可以减少无效的缓存更新。

缺点

  • 需要额外的版本控制逻辑,增加了实现复杂性。
  • 在高并发情况下,可能导致版本号冲突。

9.双写

这个方案和【2.同步更新模式(Write Through)】中的模式是一样的,同时更新数据库和缓存,并确保二者在同一时刻的一致性,只不过这里强调两个动作组成的原子性,即通过事务来保证。

在这里插入图片描述

流程

  1. 在事务中同时写入缓存和数据库。
  2. 只有在二者都成功时,提交事务。

优点

  • 能够保证数据的一致性。
  • 对于少量数据写入操作,这种方法非常有效。

缺点

  • 复杂性高,特别是在分布式系统中。
  • 事务处理可能引入性能瓶颈。

10.最终一致性

在不要求严格一致性的情况下,采用最终一致性策略,允许短期内的不一致,系统会通过后续的同步过程恢复一致性。

优点

  • 可以提高系统的可用性和性能。
  • 对于一些业务场景,最终一致性是可以接受的。

缺点

  • 需要合理设计一致性恢复的逻辑。
  • 业务逻辑复杂度增加。

总结

选择适合的策略取决于你的具体场景、业务需求和系统架构。结合这些策略,可以实现更高效的数据更新和一致性维护。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com