redis删除缓存时遇到的问题

一、redis查询key的方式

redis常用两种方式用于key的精确/模糊匹配

1. KEYS pattern

keys pattern用于匹配pattern所有key,会返回当前库里所有匹配上pattern的key,其时间复杂度为O(N),会遍历库中所有key进行匹配,并且没有数量限制,当数据库的数据量较大时,可能会造成数据库阻塞(redis单线程),该命令通常用于debug或其他特殊场景不适合用于项目编码中。

有两个很明显的 缺点

  • 没有 offset、 limit 参数,一次性吐出所有满足条件的 key ,如果实例中有非常多 key 满足条件,很难找出你需要的有效数据。
  • keys 算法是 遍历算法,复杂度是 O(n) ,如果实例中有千万级以上的 key ,这个指令就会导致 Redis 服务卡顿,所有读写 Redis 的其他指令都会被延后甚至会超时报错,因为 Redis 是 单线程程序,顺序执行所有指令,其他指令必须等到当前的 keys 指令执行完了才可以继续。

2. SCAN cursor [MATCH pattern] [COUNT count] TYPE type

2.8版本中引入了scan,与keys相比:

  • 每次调用scan的时间复杂度为O(1),遍历整个库调用的时间复杂度为O(N),但它是通过游标分步进行的,不会像keys命令一样阻塞redis的线程
  • 提供 limit 参数,可以控制每次返回结果的最大条数, limit 只是个 hint, 返回的结果可多可少
  • 同keys 一样,它也提供模式匹配功能。
  • 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数。
  • 返回的结果可能 会有重复,需要客户端去重,这点非常重要。
  • 遍历的过程中如果有数据修改,改动后的数据能不能遍历到是 不确定的
  • 单次返回的结果是空的并不意昧着遍历结束,而要看返回的 游标值是否为零。

基本用法:第一次遍历时, cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor ,一直遍历到返回的 cursor 值为 0 时结束。

它是一维数 组,是二维链表结构。第一维数组的大小总是 2的n次方 (n>=0 ),扩容一次数组,大小空间加倍, 也就是 2的n次方加1。 scan 指令返回的游标就是第一维数组的位置索引,我们将这个位置索引称为槽( slot )。

采用了高位进位加法来遍历,是为了考虑到字典的扩容和缩容时避免槽位的遍历重复和遗漏。高位进位加法从左边加,进位往右边移动,同普通加法正好相反。

假设开始槽位的二进制数是 xxx ,那么该槽位中的元素将被 rehash到 0xxx 1xxx(xxx+8)中。如果字典长度由 16 位扩容到 32 位,那么对于二进制槽位 xxxx 中的元素将被 rehash 0xxxx和1xxxx(xxxx+ 16)中

它会同时保留旧数组和新数组,然后在定时任务中以及后续对 hash 的指令操作中渐渐地将旧数组中挂接的元素迁移到新数组上。

如 zscan 遍历 zset 集合元素, hscan 遍历 hash 字典的元素, sscan 遍历 set 集合的元素。

在平时的业务开发中,要尽量避免大 key 的产生

如何定位大 key 呢? 为了避免给线上 Redis 带来卡顿,就要用到 scan 指令,对于扫描出来的每一个 key ,使用 type 指令获得 key 的类型,然后使用相应数据结构的 size 或者 len 方法来得到它的大小,对于每一种类型,将大小排名的前若干名作为扫描结果展示出来。

Original: https://www.cnblogs.com/mzBlogs/p/16624625.html
Author: 重生之我是java程序员
Title: redis删除缓存时遇到的问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/608250/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球