wordpress单本小说站,布吉网站建设哪家效益快,做一个网站需要多久,做网站 就上凡科网https://www.cnblogs.com/coderacademy/p/18137480 延迟双删
对于上面链接的文章#xff0c;里面的延迟双删没有给出具体的例子#xff0c;也没有直接指出具体解决的问题是针对那种缓存策略#xff0c;这里补充一下#xff0c;延时双删缓存针对的是Cache aside pattern(缓…https://www.cnblogs.com/coderacademy/p/18137480 延迟双删
对于上面链接的文章里面的延迟双删没有给出具体的例子也没有直接指出具体解决的问题是针对那种缓存策略这里补充一下延时双删缓存针对的是Cache aside pattern(缓存旁路策略)处理的是在高并发读写同时存在的情况下可能会出现的问题详细如下。 什么是延迟双删
延时双删策略能够有效解决缓存和数据库之间的数据不一致问题。它的核心思想是在更新数据库之后先删除缓存中的数据延迟一段时间后再次删除缓存中的数据。其具体步骤如下
更新数据库先将数据更新到数据库中。删除缓存立即删除缓存中对应的旧数据。延迟一段时间等待一段时间通常是足够长以保证并发写入完成的时间。再次删除缓存再次删除缓存中的数据以防止并发操作在缓存中留下旧数据。
tips:延迟双删需要由更新数据的那个程序去处理。
延时双删策略的应用场景 延时双删策略的应用场景通常涉及**高并发写操作**和**读取操作**同时发生的情况。以下是一个典型的具体场景展示如何出现缓存和数据库数据不一致的问题。
### 场景描述
假设有一个电商网站使用缓存如 Redis来加速商品信息的读取。例如一个商品的库存信息存储在数据库中同时也缓存到 Redis 中以便快速读取。
#### 具体流程
1. **用户A请求读取商品库存信息** - 用户A请求读取某个商品的库存信息系统会优先从缓存Redis中读取该商品的库存。如果缓存中存在则直接返回如果不存在则从数据库读取并将结果缓存起来。
2. **用户B请求更新商品库存信息** - 在用户A读取缓存中的商品库存时用户B执行了一个购买操作该操作会更新商品的库存信息。系统会先更新数据库中的商品库存然后删除缓存中的商品库存信息以确保下一次读取时会从数据库中获取最新数据。
#### 问题出现
在用户B更新商品库存后但**在删除缓存之后、更新数据库完成之前的时间窗口**内用户A再次读取商品库存信息。这会出现以下问题
- 用户B更新库存后缓存被删除但是用户A此时发起读取请求因为缓存已经被删除系统会去数据库中读取库存数据。 - 但数据库还没有完成更新操作可能因为写入操作较慢或者在执行事务用户A读取到的仍然是旧的库存信息。 - 最后数据库更新完成数据正确但用户A刚刚读取到了错误旧的库存数据导致**数据不一致**。
### 延时双删策略如何解决这个问题
为了防止上述数据不一致情况的发生可以使用延时双删策略
1. **用户B更新商品库存信息** - 更新数据库中的库存信息。 - **立即删除缓存**中的商品库存信息。 2. **用户A读取商品库存信息** - 如果在缓存被删除之后读取系统会从数据库中读取。 - 用户A读取时可能得到旧数据数据库尚未更新完成但接下来的延时操作将解决这个问题。 3. **延迟删除缓存** - 设置一个延迟例如 500 毫秒在此延迟之后再次尝试删除缓存中的商品库存信息。 - 这段延迟时间应足够长以确保数据库更新操作已经完成。
### 具体应用中的时间点
- **T1用户B请求更新库存系统开始更新数据库。** - **T2用户B更新数据库后立即删除缓存。** - **T3数据库更新操作未完成用户A读取库存发现缓存不存在转向读取数据库。** - **T4用户A读取到旧的库存数据数据库写操作未完成。** - **T5延迟一段时间如500毫秒再次删除缓存。** - **T6用户A再次请求发现缓存不存在此时数据库已更新读取到最新库存信息。**
### 为什么这个策略有效
1. **避免读取旧数据**通过在更新数据库后立即删除缓存避免缓存中存在旧数据。 2. **降低不一致的窗口期**延迟删除缓存提供了一个补偿机制以防止在数据库写入完成前的缓存穿透现象。 3. **高效读取最新数据**第二次删除缓存确保了之后的读取操作总能获取最新数据减少了缓存和数据库之间的数据不一致的风险。
### 总结
延时双删策略主要解决的是在缓存删除和数据库更新之间的短时间窗口内出现数据不一致的问题特别适用于**高并发写操作和读操作混合**的场景如电商库存更新、金融交易系统的账户余额更新等。通过这种策略系统能够更好地保障缓存和数据库之间的数据一致性。 延迟双删除golang代码示例
package mainimport (contextfmttimego.mongodb.org/mongo-driver/bsongo.mongodb.org/mongo-driver/mongogo.mongodb.org/mongo-driver/mongo/options
)func main() {// 示例更新数据库并执行延时双删策略// 示例的数据库操作ctx : context.Background()// 第一步更新数据库updateDatabase(ctx)// 第二步立即删除缓存deleteCache()// 第三步设置一个延迟任务如 500 毫秒time.AfterFunc(500*time.Millisecond, func() {deleteCache() // 再次删除缓存})fmt.Println(Database update and delayed cache deletion scheduled.)
}func updateDatabase(ctx context.Context) {// 示例数据库更新操作fmt.Println(Updating database...)// 在此处执行数据库的更新操作...
}func deleteCache() {// 示例缓存删除操作fmt.Println(Deleting cache...)// 在此处执行缓存删除操作...
}Read-Through 和Cache Aside Pattern的读有什么区别 **Read-Through** 和 **Cache Aside Pattern**又称为 **Lazy Loading** 或 **Lazy Caching**是两种常见的缓存策略它们在缓存读取读操作的实现上有一些关键区别。
### Read-Through 缓存策略
**Read-Through** 是一种由缓存层自动管理数据加载的策略读操作首先检查缓存如果缓存中没有数据缓存层会自动从后端数据源例如数据库加载数据并将其存储到缓存中然后返回给调用者。
#### 工作原理
1. **应用程序请求数据** - 应用程序向缓存层请求数据。 2. **缓存层检查数据** - 如果缓存中有数据直接返回。 - 如果缓存中没有数据缓存层会自动从后端数据源如数据库加载数据。 3. **缓存层更新缓存** - 将从后端数据源获取的数据存储到缓存中以便下次快速访问。 4. **返回数据** - 缓存层返回数据给应用程序。
#### 特点
- **自动加载数据**缓存层自动处理缓存未命中的情况将数据从后端数据源加载到缓存中。 - **透明性**应用程序不需要关心数据从哪里来缓存层会自动管理。 - **常用于缓存代理中**例如使用特定的缓存中间件或服务来管理缓存。
#### 例子
如使用 AWS ElastiCache 或 Memcached 的集成模式其中缓存中间件自动处理数据加载和缓存更新。
### Cache Aside Pattern 缓存策略
**Cache Aside Pattern**Lazy Loading是一种由应用程序主动管理缓存的数据加载的策略。应用程序在读取数据时首先检查缓存如果缓存未命中应用程序会主动从后端数据源加载数据并手动将数据写入缓存。
#### 工作原理
1. **应用程序请求数据** - 应用程序首先检查缓存中是否有数据。 2. **缓存未命中时应用程序加载数据** - 如果缓存中没有数据应用程序从后端数据源如数据库加载数据。 3. **应用程序更新缓存** - 应用程序将从后端数据源获取的数据写入缓存。 4. **返回数据** - 应用程序返回数据给调用者。
#### 特点
- **主动管理缓存**应用程序负责检查缓存、加载数据和更新缓存。 - **灵活性**应用程序可以决定何时加载和更新数据缓存的逻辑在应用程序中控制。 - **常用于手动控制缓存的场景**例如通过代码来管理缓存操作。
#### 例子
在 Go、Java 或 Python 应用中程序员在业务逻辑中手动管理从缓存中读取数据未命中时从数据库加载数据并将其写入缓存的操作。
### 区别
| 特性 | Read-Through | Cache Aside Pattern | |-------------------------------|-------------------------------------------------------|-----------------------------------------------------| | **数据加载责任** | 缓存层自动负责从后端加载数据 | 应用程序负责加载数据和更新缓存 | | **实现难度** | 较低缓存层自动管理数据加载 | 较高应用程序需要管理缓存逻辑 | | **灵活性** | 较低缓存策略由缓存层定义 | 较高应用程序可以控制何时加载和更新数据 | | **常见使用场景** | 通常用于缓存中间件或代理如 Memcached, AWS ElastiCache| 手动管理缓存的应用程序 | | **缓存未命中后的开销** | 缓存层负责处理加载应用程序不感知 | 应用程序处理加载逻辑有可能影响性能 | | **读写操作的复杂度** | 读操作简单缓存层透明处理 | 读操作复杂需要在应用中显式处理缓存和数据库访问 |
### 总结
- **Read-Through** 更适合希望透明缓存管理的场景使用缓存中间件或代理自动处理数据加载简化应用逻辑。 - **Cache Aside Pattern** 更适合需要灵活控制缓存逻辑的场景应用程序可以根据业务需求主动决定何时加载和更新缓存。