IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 一看就懂,关于Redis的缓存更新策略 -> 正文阅读

[大数据]一看就懂,关于Redis的缓存更新策略

在这里插入图片描述

业务场景:

  • 低一致性需求:使用内存淘汰机制。例如店铺类型的查询缓存
  • 高一致性需求:主动更新,并以超时剔除作为兜底方案。例如店铺详情查询的缓存

1、主动更新

  1. Cache Aside Pattern:由缓存的调用者,在更新数据库的同时更新缓存
  2. Read/Write Through Pattern:缓存与数据库整合为一个服务,由服务维护一致性,调用者调用该服务,无需关心缓存一致性问题
  3. Write Behind Caching Pattern:调用者只操作缓存,由其他线程异步的将缓存的数据持久化到数据库,保证最终一致。

PS:一般使用方案1,由缓存的调用者,在更新数据库的同时更新缓存

2、Cache Aside Pattern

由缓存的调用者,在更新数据库的同时更新缓存

操作缓存和数据库时有三个问题需要考虑:

  1. 删除缓存还是更新缓存?
  2. 如何保证缓存与数据库的操作的同时成功或失败?
  3. 先操作缓存还是先操作数据库?
1、删除缓存还是更新缓存?
  • 更新缓存:每次更新数据库都更新缓存,无效写操作较多 ?

    如果更新数据库的次数多,而读取的次数较少,则每次更新时,都会增加无效的更新缓存操作

  • 删除缓存:更新数据库时让缓存失效,查询时再更新缓存 ??

2、如何保证缓存与数据库的操作的同时成功或失败?
  • 单体系统,将缓存与数据库操作放在一个事务
  • 分布式系统,利用TCC等分布式事务方案
3、先操作缓存还是先操作数据库?
  • 先删除缓存,再操作数据库
  • 先操作数据库,再删除缓存
1、先删除缓存,再操作数据库

不存在线程安全问题场景

  1. 线程1收到请求后,先删除缓存,然后更新数据库值为20
  2. 线程2收到请求后,先查询缓存,并没有命中,则查询数据库的值为20,再写入缓存

在这里插入图片描述

存在线程安全问题场景

  1. 线程1收到请求后,先删除缓存
  2. 线程2收到查询请求,查询缓存发现没有命中,则去查询数据库的值为10
  3. 线程2将数据库的值写入缓存
  4. 线程1更新数据库的值为20,此时导致数据不一致问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传在这里插入图片描述

2、先操作数据库,再删除缓存??

不存在线程安全问题场景

  1. 线程2收到请求后更新数据库值为20
  2. 线程2更新完成后,删除缓存
  3. 线程1收到请求后,查询缓存,未命中,则查询数据库
  4. 线程1查询到数据后,写入缓存
    在这里插入图片描述

存在线程安全问题场景

  1. 线程1收到查询请求后,查询缓存,未名中,则去查询数据库值为10
  2. 线程2收到更新请求,更新数据库值为20
  3. 线程2更新数据库后,删除缓存
  4. 线程1写入缓存值为10,此时缓存写入的是旧数据

在这里插入图片描述

3、总结

缓存更新策略的最佳实践方案:

  1. 低一致性需求:使用Redis自带的内存淘汰机制
  2. 高一致性需求:主动更新,并以超时剔除作为兜底方案
    • 读操作
      • 缓存命中则直接返回
      • 缓存未命中则查询数据库,并写入缓存,设定超时时间
    • 写操作
      • 先写数据库,然后再删除缓存
      • 要确保数据库与缓存操作的原子性

4、实战

1、查询设置超时时间
@Override
public Result queryById(Long id) {
    //从redis查询缓存
    String key = RedisConstants.CACHE_SHOP_KEY + id;
    String shopInfo = stringRedisTemplate.opsForValue().get(key);
    //判断是否存在
    if (StrUtil.isNotBlank(shopInfo)){
        //存在则返回
        Shop shop = JSONUtil.toBean(shopInfo, Shop.class);
        return Result.ok(shop);
    }

    //不存在,则查询数据库
    Shop shop = getById(id);
    //不存在则返回错误
    if (null == shop){
        return Result.fail("店铺不存在");
    }

    //写入缓存 设置超时时间为30min
    stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES);
    //数据库存在,则返回

    return Result.ok(shop);
}
2、更新时删除缓存
@Override
@Transactional
public Result update(Shop shop) {
    Long id = shop.getId();
    if (null == id){
        return Result.fail("店铺id不能为空");
    }
    //1.更新数据库
    updateById(shop);
    //2.删除缓存
    stringRedisTemplate.delete(RedisConstants.CACHE_SHOP_KEY + shop.getId());

    return Result.ok();
}
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-06-06 17:25:11  更:2022-06-06 17:27:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 21:54:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码