• bbbi
    2020-10-10
    针对redis-cluster还可以使用scan命令么?

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

    共 3 条评论
    25
  • Kaito
    2020-09-18
    在 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个元素。
    展开
    共 28 条评论
    366
  • 青青子衿
    2020-09-18
    当你发现 Redis 性能变慢时,可以通过 Redis 日志,或者是 latency monitor 工具,查询变慢的请求,根据请求对应的具体命令以及官方文档,确认下是否采用了复杂度高的慢查询命令。 其实这个排除过程才是我们最想学习的,却被作者一带而过了。。。。
    共 10 条评论
    75
  • Geek_9b08a5
    2020-12-30
    第十八课: 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才可以,再到客户端进行合并
    展开
    共 3 条评论
    20
  • test
    2020-09-18
    通常线上是不能使用keys的,标准替代方案就是scan。scan不会导致redis变慢,只是如果在scan过程中kv表扩容的话可能会遇到重复key。 PS:sort的时间复杂度是O(N+M*log(M)) 是因为需要创建一个新的数字,并且用快排去排序。
    
    7
  • 花儿少年
    2021-07-23
    好像说了什么,好像又什么都没说 生产系统中出问题哪有时间整这些,赶紧恢复老板都在后面站着呢 同时这些命令,keys、集合操作基本都是被禁用的;所以正常情况下,生产系统中Redis变慢一般都是bigkey,同时过期,热点数据等等
    共 2 条评论
    6
  • 范闲
    2020-12-03
    可以利用scan命令。但是scan可能会返回重复key,使用方做个去重即可。
    
    5
  • 王益新
    2020-10-21
    "默认情况下,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 会被删除?
    共 4 条评论
    3
  • 那时刻
    2020-09-18
    前段时间时间刚好看了redis里sort的实现,说说的我的理解。sort是基于Bentley & McIlroy's Engineering a Sort Function。可以认为是partial qsort,只保证指定返回的数据(函数参数里的lrange和rrange)有序即可。在元素个数小于7的时候,采用插入排序,因为元素个数小的时候,快速排序并不高效。元素个数大大于7的时候,采用快速排序,经过这些优化之后,SORT操作复杂度为 O(N+M*log(M))。
    
    3
  • William Ning
    2022-04-01
    本机【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
    展开
    
    2