当前位置: 首页 > web >正文

Redis缓存设计与性能优化

缓存设计

缓存击穿

数据过期的时候一下子涌入大量的请求,在缓存中不存在。

  • 加互斥锁,只允许一个线程去更新缓存数据
  • 异步预热缓存

缓存穿透

  • 请求的数据根本不存在于缓存和数据库中,每次请求都会打到数据库,导致数据库压力剧增。
  • 缓存空对象。对不存在的数据也缓存一个空值,设置较短过期时间。查同一个不存在的商品进行空值延期
  • redisson布隆过滤器。
  • 参数校验。请求前先校验 userId 是否合理,比如正整数、存在合法范围

缓存雪崩

大量缓存同时失效(或者缓存层支撑不住或者宕机),请求直接打到数据库,造成数据库瞬间崩溃或响应变慢。

  • 过期时间随机化。避免大量 key 同时过期(比如加上随机 1~5 分钟)
  • 设置热点数据永远不过期。
  • 缓存预热或提前加载。系统启动时或定时任务提前加载热门缓存

热点缓存key重建优化

使用分布式锁和dcl(双重检查),只允许一个线程去更新缓存数据。好处是全局一把锁并且一把锁只锁一个对应需要重建的数据。

优化:确定得出数据的时间可以使用trylock避免大量的锁逻辑

缓存与数据库双写不一致

  1. 双写不一致
    双写不一致
  2. 读写并发不一致
    在这里插入图片描述
    解决方案:
  • 一致性要求不高,设置合理的过期时间+每隔一段时间触发读的主动更新
  • 延迟双删。缺点会让每个更新操作都延时
  • 高一致性的情况。对更新缓存的操作加分布式锁,优化可以使用分布式读写锁(因为写数据库要更新缓存,读数据库也要更新缓存(在缓存没对应数据的情况))
  • 引入中间件canal监听binlog修改缓存

读多写少的情况加入缓存提高性能,写多读多的情况又不能容忍缓存数据不一致就不要加缓存了。

开发规范与性能优化

键值设计

  1. key名设计:可读性、可管理性和简洁性。以业务名或者数据库名为前缀用冒号分隔拼接,key名称不宜过长。不要包含特殊字符
  2. value设计:拒绝bigkey(防止网卡流量、慢查询)
    字符串类型为超过10KB,非字符串类型元素超过5000属于大key
  3. bigkey的危害,getall导致redis阻塞,网络拥塞,过期删除时候没有过期异步删除会阻塞redis
  4. 如何优化bigkey
  • 对大key数据拆分经过hash分开存入big list: list1、list2、…listN
  • 如果bigkey不可避免,也要尽量避免getall和直接删除所有字段,可以分批删除
  • 控制key的生命周期,使用expire设置过期时间
  • 选择适合的数据类型

命令使用

  • O(N)命令关注N的数明确N的值。有遍历的需求可以使用scan代替。
  • 禁用命令,禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令
  • 合理使用select,redis的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰。
  • 使用批量操作提高效率例如mget、mset、pipeline,但要注意控制一次批量操作的元素个数(例如500以内,实际也和元素字节数有关)。

原生命令是原子操作,pipeline是非原子操作。pipeline可以打包不同的命令,原生命令做不到。pipeline需要客户端和服务端同时支持。

  • Redis事务功能较弱,不建议过多使用,可以用lua替代

客户端使用

  1. 避免多个应用使用一个Redis实例
  2. 使用带有连接池的数据库,可以有效控制连接,同时提高效率

有需要时可以对连接池预热

  1. 高并发下添加熔断功能

  2. 设置合理的密码,如有必要可以使用SSL加密访问

  3. Redis过期键有三种清除策略

    • 被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key
    • 主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key
    • 当前已用内存超过maxmemory限定时,触发主动清理策略
    1. 过期时间的key
      • volatile-ttl:在筛选时,会针对设置了过期时间的键值对,根据过期时间的先后进行删除,越早过期的越先被删除。
      • volatile-random:就像它的名称一样,在设置了过期时间的键值对中,进行随机删除。
      • volatile-lru:会使用 LRU 算法筛选设置了过期时间的键值对删除。
      • volatile-lfu:会使用 LFU 算法筛选设置了过期时间的键值对删除。
    2. 所有的key
      • allkeys-random:从所有键值对中随机选择并删除数据。
      • allkeys-lru:使用 LRU 算法在所有数据中进行筛选删除。
      • allkeys-lfu:使用 LFU 算法在所有数据中进行筛选删除。
    3. 不处理
      • noeviction:不会剔除任何数据,在内存上限时拒绝所有写入操作并返回客户端错误信息"(error) OOM command not allowed when used memory",此时Redis只响应读操作。
    • LRU 算法(Least Recently Used,最近最少使用)淘汰很久没被访问过的数据,以最近一次访问时间作为参考。(默认推荐)
    • LFU 算法(Least Frequently Used,最不经常使用)淘汰最近一段时间被访问次数最少的数据,以次数作为参考。

当存在热点数据时,这时使用LFU可能更好点。
LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中率急剧下降。

策略核心思想应对场景
LRU淘汰最近最少使用的键应对时间敏感的缓存访问模式
LFU淘汰历史访问频率最低的键应对长期热点数据的缓存使用场景

配置淘汰算法

maxmemory 256mb
maxmemory-policy allkeys-lru
CONFIG SET maxmemory 256mb
CONFIG SET maxmemory-policy volatile-lru
  1. 不配置最大内存的情况,redis会无限制的使用虚拟内存(使用硬盘模拟内存),性能下降。
http://www.xdnf.cn/news/9465.html

相关文章:

  • 题目 3316: 蓝桥杯2025年第十六届省赛真题-数组翻转
  • mac 下安装Rust Toolchain(Nightly)
  • Redis--缓存穿透与缓存雪崩详解及解决方案
  • Cloudera Manager 学习笔记
  • 程序的 “内存舞台”:深入解析虚拟地址空间与内存管理
  • 3D Tiles高级样式设置与条件渲染(4)
  • 8Manage PM、Trello与飞书对比评测:哪款项目管理软件更适合企业使用?
  • 《仿盒马》app开发技术分享-- 确认订单页(数据展示)(端云一体)
  • 程序开发的 “瑞士军刀”:深入解析库文件的原理与实践
  • 六大常用查找算法对比分析
  • 电气行业PLM应用案例:国产PLM助力山西氪安研发转型
  • P1903 [国家集训队] 数颜色 / 维护队列(单点修改莫队)
  • 借教室--二分+查分
  • vue2 一分钟不动系统 系统将进行锁定
  • Android系统 TinyAlsa命令
  • 计算机科技笔记: 容错计算机设计05 n模冗余系统 特殊的双模系统 复杂结构 非并行串行结构的两种计算方法
  • 4.GIS迁移步骤+注意事项+部署常见问题
  • Keepalived 配置 VIP 的核心步骤
  • 西门子-队列
  • SaaS与私有部署:企业如何选择同城O2O外卖跑腿APP开发方案?
  • 第五章 文件内容显示
  • java每日精进 5.27【异步实现】
  • C3P0连接池的使用方法和源码分析
  • Linux系统 - 系统编程概念
  • 【Redis】常用的数据类型 + 单线程模型
  • 答疑:鲜羊奶如何助力亲子关系平衡?
  • 全志V853 mpp程序开发
  • Python训练营---Day38
  • Kubernetes 中的CRD(Custom Resource Definition)与Operator详解
  • Web前端入门:JavaScript 运算符 == 和 === 有什么区别?