首页 > 数据库 >记录Redis+MQ延迟双删保证缓存一致性

记录Redis+MQ延迟双删保证缓存一致性

时间:2024-10-18 22:49:07浏览次数:20  
标签:缓存 删除 双删 数据库 Redis 更新 MQ blogId 延迟

场景描述

在博客系统中,用户可以给博客点赞或者评论,这些操作需要更新数据库中的数据,同时要保证缓存中的博客信息与数据库保持一致。为了提高性能,博客数据会存放在Redis缓存中。但当有大量用户同事点赞或是评论时,缓存和数据库中的数据可能出现不一致。

何谓延迟双删?

延迟双删的核心思想:更新数据库数据的同时,处理Redis缓存中的数据,以避免缓存和数据库中的数据不一致。

双删

在更新数据库之前删除缓存中的博客数据
更新数据库之后,为了防止第一次删除缓存和数据库更新之间,产生新的缓存(一个新的并发请求产生在删除缓存之后,更新数据库之前再次写入了旧缓存,导致不一致问题),所以在更新数据库后的一,延迟一段时间再次删除缓存。

实现步骤

  1. 当用户点赞或评论某篇博客时,首先将Redis缓存中对应的博客数据删除
public void deleteCacheBeforeUpdate(Long blogId) {
    // 删除Redis中缓存的博客数据
    redisTemplate.delete("blog:" + blogId);
}
  1. 更新数据库
public void updateBlogInDatabase(Long blogId) {
    // 假设有一个点赞服务或评论服务,执行数据库更新
    blogService.updateLikeCount(blogId); // 点赞操作
    // 或者
    blogService.updateCommentCount(blogId); // 评论操作
}
  1. 延迟删除缓存(通过RabbitMQ异步处理)
    发送延迟删除缓存的消息到RabbitMQ:更新数据库后,将延迟删除的任务放入RabbitMQ消息队列,并设置一个适当的延迟时间
public void sendDelayedCacheDeletion(Long blogId) {
    // 发送博客ID到RabbitMQ消息队列,延迟一段时间后删除缓存
    rabbitTemplate.convertAndSend("cache-delete-queue", blogId);
}

RabbitMQ监听消息,进行第二次缓存删除操作。

@RabbitListener(queues = "cache-delete-queue")
public void handleCacheDelete(Long blogId) {
    try {
        // 设置延迟时间,比如500毫秒 可以采用延迟队列
        Thread.sleep(500); // 模拟延迟
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    // 删除Redis缓存中的博客数据
    redisTemplate.delete("blog:" + blogId);
}

执行逻辑:

// 1. 删除缓存,确保读取的下一次是最新数据
deleteCacheBeforeUpdate(blogId);

// 2. 更新数据库中的博客点赞数或评论数
updateBlogInDatabase(blogId);

// 3. 发送延迟删除缓存的消息到RabbitMQ
sendDelayedCacheDeletion(blogId);

以上方案可以在一定程度上保证缓存一致性,但不是绝对的,在某些极端情况下还是会存在缓存不一致的情况。可以结合分布式锁来确保缓存的一致性。在更新数据库和处理缓存删除的过程中,通过锁机制保证只有一个线程可以操作缓存,从而避免多个线程并发地写入缓存。

最后,延迟双删策略虽然能有效解决大部分并发下的缓存一致性问题,但在极端高并发场景中仍可能会出现短暂的不一致。通过引入分布式锁,可以进一步增强缓存和数据库之间的一致性,确保在并发操作时只有一个线程能够执行缓存和数据库的操作。此外,如果对一致性要求更高,还可以在数据库更新后直接更新缓存而不是删除缓存,进一步提高数据的一致性。或者直接更新缓存,cache优于DB的情景。

标签:缓存,删除,双删,数据库,Redis,更新,MQ,blogId,延迟
From: https://blog.csdn.net/weixin_52630811/article/details/143062546

相关文章

  • Redis架构演进之单机版Redis和数据持久化
    单机版Redis假设现在有一个业务应用,需要引入Redis来提高应用的性能,此时可以选择部署一个单机版的Redis来使用业务应用可以把Redis当作缓存来使用,从MySQL里查询数据,然后写入Redis中,之后业务应用再从Redis里读取数据,因为Redis的数据都是存储在内存里的,所以整体的速度很快。......