Redis 核心技术与实战
蒋德钧
中科院计算所副研究员
81696 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 53 讲
开篇词 (1讲)
实践篇 (28讲)
Redis 核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

18 | 波动的响应延迟:如何应对变慢的Redis?(上)

解决方法
影响
解决方法
影响
过期key操作
慢查询命令
Redis自身操作特性的影响
基于当前环境下的Redis基线性能做判断
查看Redis的响应延迟
如何应对Redis变慢
判断Redis是否变慢
怎样应对变慢的Redis

该思维导图由 AI 生成,仅供参考

你好,我是蒋德钧。
在 Redis 的实际部署应用中,有一个非常严重的问题,那就是 Redis 突然变慢了。一旦出现这个问题,不仅会直接影响用户的使用体验,还可能会影响到“旁人”,也就是和 Redis 在同一个业务系统中的其他系统,比如说数据库。
举个小例子,在秒杀场景下,一旦 Redis 变慢了,大量的用户下单请求就会被拖慢,也就是说,用户提交了下单申请,却没有收到任何响应,这会给用户带来非常糟糕的使用体验,甚至可能会导致用户流失。
而且,在实际生产环境中,Redis 往往是业务系统中的一个环节(例如作为缓存或是作为数据库)。一旦 Redis 上的请求延迟增加,就可能引起业务系统中的一串儿“连锁反应”。
我借助一个包含了 Redis 的业务逻辑的小例子,简单地给你解释一下。
应用服务器(App Server)要完成一个事务性操作,包括在 MySQL 上执行一个写事务,在 Redis 上插入一个标记位,并通过一个第三方服务给用户发送一条完成消息。
这三个操作都需要保证事务原子性,所以,如果此时 Redis 的延迟增加,就会拖累 App Server 端整个事务的执行。这个事务一直完成不了,又会导致 MySQL 上写事务占用的资源无法释放,进而导致访问 MySQL 的其他请求被阻塞。很明显,Redis 变慢会带来严重的连锁反应。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Redis性能问题是常见的挑战,本文深入探讨了Redis突然变慢的原因及解决方法。首先介绍了判断Redis是否变慢的方法,包括查看响应延迟和基线性能。然后重点讨论了两类关键操作对性能的影响:慢查询命令和过期key操作。针对慢查询命令,提出了替换高效命令、客户端完成操作等解决方法;对于过期key操作,详细介绍了过期key的自动删除机制及解决方法。文章强调了排查和解决Redis性能问题的章法,建议读者按部就班地排查,同时指出了除了了解Redis本身原理外,还需了解和Redis交互的底层系统的关键机制。整体而言,本文内容丰富,对于遇到Redis性能问题的读者具有很高的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 核心技术与实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(37)

  • 最新
  • 精选
  • bbbi
    针对redis-cluster还可以使用scan命令么?

    作者回复: Redis cluster模式下不支持跨节点的SCAN操作,要想得到整个集群的SCAN结果,可以遍历每个节点,分别进行SCAN操作,然后在客户端合并结果。 另外有一个方法,是可以用Hash Tag,也就是在键值对的key中使用花括号{},例如{user:}1, {user:}2这样。Redis cluster会针对花括号中的部分进行哈希,这样可以把具有相同前缀的key分配到同一个哈希槽里面。不过,这个方法的潜在风险是:大量相同前缀的key被分配到同一个哈希槽里面了,会导致数据在哈希槽之间分布不均衡。如果要用这个方法,需要评估下key的分布情况。

    2020-10-10
    3
    28
  • Kaito
    在 Redis 中,还有哪些其他命令可以代替 KEYS 命令,实现同样的功能呢?这些命令的复杂度会导致 Redis 变慢吗? 如果想要获取整个实例的所有key,建议使用SCAN命令代替。客户端通过执行SCAN $cursor COUNT $count可以得到一批key以及下一个游标$cursor,然后把这个$cursor当作SCAN的参数,再次执行,以此往复,直到返回的$cursor为0时,就把整个实例中的所有key遍历出来了。 关于SCAN讨论最多的问题就是,Redis在做Rehash时,会不会漏key或返回重复的key。 在使用SCAN命令时,不会漏key,但可能会得到重复的key,这主要和Redis的Rehash机制有关。Redis的所有key存在一个全局的哈希表中,如果存入的key慢慢变多,在达到一定阈值后,为了避免哈希冲突导致查询效率降低,这个哈希表会进行扩容。与之对应的,key数量逐渐变少时,这个哈希表会缩容以节省空间。 1、为什么不会漏key?Redis在SCAN遍历全局哈希表时,采用*高位进位法*的方式遍历哈希桶(可网上查询图例,一看就明白),当哈希表扩容后,通过这种算法遍历,旧哈希表中的数据映射到新哈希表,依旧会保留原来的先后顺序,这样就可以保证遍历时不会遗漏也不会重复。 2、为什么SCAN会得到重复的key?这个情况主要发生在哈希表缩容。已经遍历过的哈希桶在缩容时,会映射到新哈希表没有遍历到的位置,所以继续遍历就会对同一个key返回多次。 SCAN是遍历整个实例的所有key,另外Redis针对Hash/Set/Sorted Set也提供了HSCAN/SSCAN/ZSCAN命令,用于遍历一个key中的所有元素,建议在获取一个bigkey的所有数据时使用,避免发生阻塞风险。 但是使用HSCAN/SSCAN/ZSCAN命令,返回的元素数量与执行SCAN逻辑可能不同。执行SCAN $cursor COUNT $count时一次最多返回count个数的key,数量不会超过count。 但Hash/Set/Sorted Set元素数量比较少时,底层会采用intset/ziplist方式存储,如果以这种方式存储,在执行HSCAN/SSCAN/ZSCAN命令时,会无视count参数,直接把所有元素一次性返回,也就是说,得到的元素数量是会大于count参数的。当底层转为哈希表或跳表存储时,才会真正使用发count参数,最多返回count个元素。
    2020-09-18
    28
    376
  • 青青子衿
    当你发现 Redis 性能变慢时,可以通过 Redis 日志,或者是 latency monitor 工具,查询变慢的请求,根据请求对应的具体命令以及官方文档,确认下是否采用了复杂度高的慢查询命令。 其实这个排除过程才是我们最想学习的,却被作者一带而过了。。。。
    2020-09-18
    10
    75
  • Geek_9b08a5
    第十八课: 1.作者讲了什么? 当redis查询变慢了怎么办,如何排查,如何进行处理? 2.作者是怎么把这件事将明白的? 1、通过分析redis各组件及硬件,找出问题所在 3.为了讲明白,作者讲了哪些要点,哪些亮点? 1、亮点:通过redis-cli --intrinsic-latency 120可以得知redis的基准线。后续可以根据基准线的响应速度进行判断是否查询慢,这是我之前所不知道的判断方法 2、要点:基于自己对 Redis 本身的工作原理的理解,并且结合和它交互的操作系统、存储以及网络等外部系统关键机制,再借助一些辅助工具来定位原因,并制定行之有效的解决方案 3、要点:Redis 自身操作特性的影响 1. 慢查询命令:命令操作的复杂度有关 排查方法:通过 Redis 日志,或者是 latency monitor 工具,查询变慢的请求 解决方法:1.用其他高效命令代替。如不要使用keys查询所有key,可以使用scan进行查询,不会阻塞线程 2.当你需要执行排序、交集、并集操作时,可以在客户端完成,而不要用 SORT、SUNION、SINTER 这些命令,以免拖慢 Redis 实例。 2.过期 key 操作:redis本身的内存回收机制会造成redis操作阻塞,导致性能变慢(Redis 4.0 后可以用异步线程机制来减少阻塞影响) 导致原因:大批量的key同时间内过期,导致删除过期key的机制一直触发,引起redis操作阻塞 解决方法:对key设定过期时间时,添加一个删除的时间随机数,能避免key存在同一时间过期 4、要点:redis删除过期key的机制,每100毫秒对一些key进行删除。算法如下 1.采样 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 个数的 key,并将其中过期的 key 全部删除; 2.如果超过 25% 的 key 过期了,则重复删除的过程,直到过期 key 的比例降至 25% 以下。 4.对于作者所讲的,我有哪些发散性思考? 5.将来在哪些场景里,我能够使用它? 6.留言区收获 1.在生产环境中,可以使用scan替代keys命令(答案来自@kaito 大佬) 当scan在Redis在做Rehash时,会不会漏key或返回重复的key? 1.不漏keys:Redis在SCAN遍历全局哈希表时,采用*高位进位法*的方式遍历哈希桶(可网上查询图例,一看就明白),当哈希表扩容后,通过这种算法遍历,旧哈希表中的数据映射到新哈希表,依旧会保留原来的先后顺序,这样就可以保证遍历时不会遗漏也不会重复。 2.key重复:这个情况主要发生在哈希表缩容。已经遍历过的哈希桶在缩容时,会映射到新哈希表没有遍历到的位置,所以继续遍历就会对同一个key返回多次。处理方法是在客户端直接做重复过滤 2.在redis-cluster中,不能使用一次scan在整个集群中获取所有的key,只能通过在每个实例上单独执行scan才可以,再到客户端进行合并
    2020-12-30
    3
    20
  • test
    通常线上是不能使用keys的,标准替代方案就是scan。scan不会导致redis变慢,只是如果在scan过程中kv表扩容的话可能会遇到重复key。 PS:sort的时间复杂度是O(N+M*log(M)) 是因为需要创建一个新的数字,并且用快排去排序。
    2020-09-18
    7
  • 花儿少年
    好像说了什么,好像又什么都没说 生产系统中出问题哪有时间整这些,赶紧恢复老板都在后面站着呢 同时这些命令,keys、集合操作基本都是被禁用的;所以正常情况下,生产系统中Redis变慢一般都是bigkey,同时过期,热点数据等等
    2021-07-23
    2
    6
  • 范闲
    可以利用scan命令。但是scan可能会返回重复key,使用方做个去重即可。
    2020-12-03
    5
  • 王益新
    "默认情况下,Redis 每 100 毫秒会删除一些过期 key,具体的算法如下:采样 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 个数的 key,并将其中过期的 key 全部删除,ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP默认是 20,那么,一秒内基本有 200 个过期 key 会被删除。" 这里的采样是什么意思?获取ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP个过期的key吗?那为什么说是其中过期的key? 如果采样得到的不全是过期的key,一秒内怎么还会有 200 个过期 key 会被删除?
    2020-10-21
    5
    4
  • 那时刻
    前段时间时间刚好看了redis里sort的实现,说说的我的理解。sort是基于Bentley & McIlroy's Engineering a Sort Function。可以认为是partial qsort,只保证指定返回的数据(函数参数里的lrange和rrange)有序即可。在元素个数小于7的时候,采用插入排序,因为元素个数小的时候,快速排序并不高效。元素个数大大于7的时候,采用快速排序,经过这些优化之后,SORT操作复杂度为 O(N+M*log(M))。
    2020-09-18
    3
  • William Ning
    本机【Mac M1】运行情况如下: ➜ bin ./redis-cli --intrinsic-latency 120 Max latency so far: 1 microseconds. Max latency so far: 3 microseconds. Max latency so far: 5 microseconds. Max latency so far: 7 microseconds. Max latency so far: 17 microseconds. Max latency so far: 33 microseconds. Max latency so far: 34 microseconds. Max latency so far: 35 microseconds. Max latency so far: 39 microseconds. Max latency so far: 46 microseconds. Max latency so far: 48 microseconds. Max latency so far: 59 microseconds. Max latency so far: 75 microseconds. Max latency so far: 109 microseconds. Max latency so far: 155 microseconds. Max latency so far: 583 microseconds. Max latency so far: 1073 microseconds. Max latency so far: 1127 microseconds. Max latency so far: 7119 microseconds. Max latency so far: 9128 microseconds. 2686736240 total runs (avg latency: 0.0447 microseconds / 44.66 nanoseconds per run). Worst run took 204371x longer than the average latency. ➜ bin
    2022-04-01
    2
收起评论
显示
设置
留言
37
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部