• 请不要在回答技术问题时复制粘贴 AI 生成的内容
noble4cc
V2EX  ›  程序员

redis 大 key 导致读取和删除性能降低的原因是什么呢?

  •  
  •   noble4cc · Oct 20, 2020 · 4325 views
    This topic created in 2074 days ago, the information mentioned may be changed or developed.

    一个 key 大约 1M 的话,读取性能会退化成几十毫秒,如果 1k 的话只有几毫秒,按道理说读取内存性能很高的呀,为什么退化的这么严重

    23 replies    2020-10-21 16:04:54 +08:00
    codehz
        1
    codehz  
       Oct 20, 2020
    (你是不是没考虑到网络传输
    BoarBoar
        2
    BoarBoar  
       Oct 20, 2020
    不负责任猜测,是因为 key 过大的话在内存中分配成不连续地址了,从数组变成了链表
    Narcissu5
        3
    Narcissu5  
       Oct 20, 2020
    redis 要首先针对 key 计算 hash,如果 hash 冲突了还得比较,估计慢在这里了
    caola
        4
    caola  
       Oct 20, 2020
    key 搞那长?还不如转为短的 key,再把完整的内容放到 hash 表里
    justseemore
        5
    justseemore  
       Oct 20, 2020
    我感觉也是网络因素..
    noble4cc
        6
    noble4cc  
    OP
       Oct 20, 2020
    @codehz 本机测试的,网络传输忽略,网络传输确实会,大了 tcp 要分好几个包,但是我觉得这不是根本原因,就算把测试 key 缩小为 1.5k ,一个包可以传输,1.5k 的 key 耗时涨的也挺过分的,好几毫秒的 get 请求不正常
    noble4cc
        7
    noble4cc  
    OP
       Oct 20, 2020
    @caola 不是 key 是,key 对应的 value
    kerro1990
        8
    kerro1990  
       Oct 20, 2020
    1M 内存质量不行的话,寻址都会废
    4771314
        9
    4771314  
       Oct 20, 2020
    寻址慢吧
    zeroday
        10
    zeroday  
       Oct 20, 2020
    总要遍历一遍把 value 取出来吧...你 key 越大遍历的越久,能不慢吗...
    Jooooooooo
        11
    Jooooooooo  
       Oct 20, 2020
    卡在网卡上了
    gitgabige
        12
    gitgabige  
       Oct 20, 2020
    1M 大的 key ???
    katsusan
        13
    katsusan  
       Oct 20, 2020 via iPhone
    用户态内存复制到内核缓冲区吧,另外 ram 的存取不命中 cache 的话本来也不快,大概要六七十纳秒起步。
    scriptB0y
        14
    scriptB0y  
       Oct 20, 2020
    感觉是楼上说的内存寻址的问题…… 可以考虑使用 https://redis.io/commands/unlink 命令删除,这个是立即返回的。
    la2la
        15
    la2la  
       Oct 20, 2020
    @scriptB0y 抱歉,没有必要替极客时间推广,只是提供一种排查思路,因为可能造成这个问题的原因有很多,从服务器性能到网络 IO 都有可能,正好最近在看这个东西还不错就提了一下。已删除图片链接
    noble4cc
        16
    noble4cc  
    OP
       Oct 20, 2020
    @zeroday 字符串为什么要遍历
    laminux29
        17
    laminux29  
       Oct 20, 2020
    这种有源码的东西,直接调试一下不就知道原因了,上面一堆人瞎猜我也是醉了,这种事情能猜准?
    Mirana
        18
    Mirana  
       Oct 20, 2020
    1. redisdb 本身就是个大哈希表,读取和插入都要对 key 做一次哈希找到对应的 slot,对 1m 数据做哈希和 1k 数据做哈希有性能差别
    2. 网络耗时增加
    FutherAll
        19
    FutherAll  
       Oct 20, 2020 via iPhone
    大 key 问题指的是 key 对应的 value 大,为什么这么多说 key 大的,key 如果到 kb 级别,感觉是 key 的设计有问题。

    value 过大,比如 string 到 100KB 这种,其它容器类的比如 list zset 元素个数过多,读取和写入就会耗费大量内存和 CPU,阻塞其它操作;集群模式的话单个节点很容易压力多大。再叠加热 key 之类的,节点很容易就被打崩了。
    u2r1Hqo6HExmNsrt
        20
    u2r1Hqo6HExmNsrt  
       Oct 21, 2020
    @laminux29 具体怎么做?自己加 log 编译一个版本出来调试?还是直接编译+断点调试?
    noble4cc
        21
    noble4cc  
    OP
       Oct 21, 2020
    @Mirana 是 key 对应的 value 大,一般 key 不会多大
    wiewiewie
        22
    wiewiewie  
       Oct 21, 2020
    redis 6 呢?
    salaryfly
        23
    salaryfly  
       Oct 21, 2020
    简短的说一下:
    1. 如果有大 key 存在,那么在进行复杂度为 O(n)的操作时,耗时会线性增长。
    2. Redis 被设计为基于单线程模型,这意味着某些高耗时操作会导致整体服务操作超时。

    一个很典型的例子就是 DEL 和 UNLINK, DEL 是 O(n)的阻塞操作,会导致耗时过高;而 UNILINK 是 O(1)的操作,基本不会有超时情况。两者的主要区别是 UNLINK 用后台线程处理需要删除的数据的内存释放。从这一点也可以看出,删除大 Key 的超时是因为镜像内存释放操作的原因。

    antirez:Redis is very fast as long as you use O(1) and O(log_N) commands.

    PS. 如果对这个问题有更深的兴趣或者想讨论一些技术问题,
    欢迎关注公众号留言交流: Salaryfly
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   901 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 68ms · UTC 21:12 · PVG 05:12 · LAX 14:12 · JFK 17:12
    ♥ Do have faith in what you're doing.