18 | 波动的响应延迟:如何应对变慢的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
《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-10328 - 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-1828376
- 青青子衿当你发现 Redis 性能变慢时,可以通过 Redis 日志,或者是 latency monitor 工具,查询变慢的请求,根据请求对应的具体命令以及官方文档,确认下是否采用了复杂度高的慢查询命令。 其实这个排除过程才是我们最想学习的,却被作者一带而过了。。。。2020-09-181075
- 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-30320
- test通常线上是不能使用keys的,标准替代方案就是scan。scan不会导致redis变慢,只是如果在scan过程中kv表扩容的话可能会遇到重复key。 PS:sort的时间复杂度是O(N+M*log(M)) 是因为需要创建一个新的数字,并且用快排去排序。2020-09-187
- 花儿少年好像说了什么,好像又什么都没说 生产系统中出问题哪有时间整这些,赶紧恢复老板都在后面站着呢 同时这些命令,keys、集合操作基本都是被禁用的;所以正常情况下,生产系统中Redis变慢一般都是bigkey,同时过期,热点数据等等2021-07-2326
- 范闲可以利用scan命令。但是scan可能会返回重复key,使用方做个去重即可。2020-12-035
- 王益新"默认情况下,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-2154
- 那时刻前段时间时间刚好看了redis里sort的实现,说说的我的理解。sort是基于Bentley & McIlroy's Engineering a Sort Function。可以认为是partial qsort,只保证指定返回的数据(函数参数里的lrange和rrange)有序即可。在元素个数小于7的时候,采用插入排序,因为元素个数小的时候,快速排序并不高效。元素个数大大于7的时候,采用快速排序,经过这些优化之后,SORT操作复杂度为 O(N+M*log(M))。2020-09-183
- 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. ➜ bin2022-04-012
收起评论