Day9 Redis补充

过期键缓存清除策略

  • 清除策略

    • 惰性删除(被动)当读写一个已经过期的key时,会直接删除掉这个key,然后返回空,但如果一个key一直没有访问,就会一直存在内存里
    • 定期删除(主动) redis每隔100ms触发一次定时任务,随机抽取一批设置了过期时间的key,发现已过期就直接删掉,未过期的保留
    • 策略删除 当内存达到maxmemory上线时,触发内存淘汰机制
  • 内存淘汰策略,共8种

    maxmemory-policy默认是noeviction,推荐使用volatile-lru,如果访问模式稳定,volatile-lfu的命中率会更高些,一定要设置maxmemory,否则redis到达机器内存上限时,内存数据会开始频繁跟磁盘发生交换

    • volatile-ttl 设置了过期时间的key,根据过期时间先后删除,优先淘汰剩余存活时间短的
    • volatile-random 对设置了过期时间的key随机淘汰
    • volatile-lru 对设置了过期时间的key,使用LRU(最近最少使用)算法淘汰
    • volatile-lfu 对设置了过期时间的key,使用LFU(最少频次使用)算法淘汰
    • allkeys-random 对所有key进行随机淘汰
    • allkeys-lru 对所有key,使用LRU(最近最少使用)算法淘汰
    • allkeys-lfu 对所有key,使用LFU(最少频次使用)算法淘汰
    • noeviction 不处理,拒绝写入并返回OOM command not allowed
  • LRU与LFU

    • LRU 最近最少使用,最近没访问过的先淘汰。
      • 对于访问频次很少但最近有访问过的,短期内不会删除,会污染缓存
    • LFU 最少频次使用,访问次数最少的先淘汰。

HotKey

指在有限时间内被高频访问的key,可分为有预期的热点和无预期的热点

  • 有什么危害?
    • 容易引起请求排队,集群模式下流量会严重倾斜,严重时可能导致服务瘫痪
  • 怎样算热点key?
    • 参考阿里云定义

      image.png

  • 怎么发现?
    • 业务预判
    • redis-cli —hotkeys命令
    • 客户端埋点
    • Proxy代理层收集
  • 如何优化?
    • 热点key拆分

    • 多级缓存 在redis前加一层本地缓存

      本地缓存可以减少网络请求,提高性能,缓解远程缓存压力;但是空间大小有限,不支持大量数据存储,重启程序数据会丢失,也有可能跟远程缓存数据不一致

    • 读写分离 读请求放在从节点

    • 限流降级 限制请求流量,保系统优先

JDHotKey热点探测系统

  • 核心目标
    • 实时性 热点发现延迟小于等于1s
    • 低开销 对业务代码无入侵
    • 高吞吐 支持百万级QPS的key流量分析
    • 自动应对 发现热点key后自动推送到本地缓存
    • 动态适应 热点变化快速收敛或释放
  • 架构方案
    • Agent代理
      • 内嵌client客户端,无需独立部署,随client启动
      • client用于拦截Redis调用,采集key访问数据
      • 使用时间滑动窗口统计每个key的访问频次
      • 高频过滤,只上报疑似key,避免海量普通key上报
      • 本地缓存防护
        • 一旦收到热key通知,自动缓存到本地
        • 写操作走原链路,可配合本地缓存实效广播
    • Center中心
      • worker集群 汇总client上报数据,实时计算热点阈值,判定热key并下发热key

        热key判定算法 动态阈值:基于历史流量自动调整 突发检测:使用指数加权移动平均识别流量突增 防抖机制:避免频繁上下线 热key下发 通过websocket/tcp实时推送,支持分级热度

      • etcd集群 存储规则配置,worker ip,热key列表,提供监听订阅

    • Dashboard控制台
      • 可视化配置热key匹配策略
      • 监控结果
  • 实现能力
    • 毫秒级保护
    • 熔断降级 center不可用时,agent自动退化为本地简单限流
    • 分级热度 热度策略差异化
    image.png

Redis扩展

  • RedisJson

    提供对json数据的原生支持,可以对json中的数据进行增删改查等操作

    • 相比于string的优势
      • 存储json数据性能更高,底层以二进制格式存储,相比文本格式,读写性能高,也更节省内存
      • 采用树状结构存储json,可以快速访问子元素
      • 生态集成度高
  • BloomFilter

    • 只能加数据,不能删数据,有变动时只能重建
    • BF.RESERVE bf 0.01 1000 NONSCALING
  • CuckooFilter

    • 相比于BloomFilter,新增了删除指令 指令以CF开头
    • CF.RESERVE cf 1000 BUSKETSIZE 2 MAXITERATIONS 20 EXPANSION 1

Redis常用类型底层数据结构

可以使用object encoding key查看底层实现类型

  • String字符串

    基本的数据单元,可以存储字符串、整数或者浮点数

    底层用SDS(简单动态字符串Simple Dynamic String)小数据量编码使用embstr/int类型,大数据量编码使用raw类型,切换阈值为44

    image.png

    image.png

  • List列表

    简单的列表,最多存储40亿个成员,底层使用双向链表,两端操作性能高,随机读写性能低

    使用要注意大key问题

    小数据量使用listpack(7之前是ziplist)大数据量使用quicklist,切换阈值为512个元素或单元素超64字节

    ziplist 是一块连续内存,把所有元素紧凑地挨在一起存,省内存空间但不适合大量数据

    每个entry都要记录上一个节点的长度,如果前面插入了一个大元素,那么后面数据的prev_entry_length就都得扩容,会触发连锁更新

    image.png

    listpack 一种紧凑型序列化数据结构,把数据直接按字节序列存储,用于替代ziplist

    主要差别就是Entry内部结构发生改变 listpack不再记录前一个entry的长度,而是记录自己的长度

    image.png

    quicklist 是用双向链表串联的一堆ziplist/listpack,将连续的大量数据分散,解决更新时需要操作大量节点的痛点,此外quicklist还支持对中间节点做LZF压缩

    image.png

  • Hash哈希表

    简单的键值对集合,每个键值对可以储存多个字段,最多存储40亿个成员

    相比string操作消耗更小,也能节省存储空间,但使用时要注意大key问题,过期时间不能作用在field上,有局限性

    小数据量使用listpack,大数据量使用hashtable,切换阈值为512字段或单值超64字节

  • Set集合

    一个无序集合,最多存储40亿个成员

    小数据量使用intset/listpack 大数据量用hashtable,新增、删除、查找复杂度都是O(1),切换阈值为512个元素或含非整数

  • ZSet有序集合

    一个有排序的集合,最多存储40亿个成员

    小数据量使用listpack,大数据量使用skiplist+hashtable,切换阈值为128个元素或单值超64字节

    skiplist 就是多层链表,底层保存全部元素,上层是下层的子集

    随机层级概率算法,每次循环有25%的概率加一层,redis7最多32层,能够存储2^64个元素 第一层 75%的节点 第二层 25%的节点 第三层 6.25%的节点 第n层 0.25^(n-1)的节点

    image.png

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP