V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
noble4cc
V2EX  ›  程序员

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

  •  
  •   noble4cc · 2020-10-20 15:43:12 +08:00 · 3774 次点击
    这是一个创建于 1500 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    value 过大,比如 string 到 100KB 这种,其它容器类的比如 list zset 元素个数过多,读取和写入就会耗费大量内存和 CPU,阻塞其它操作;集群模式的话单个节点很容易压力多大。再叠加热 key 之类的,节点很容易就被打崩了。
    Nillouise
        20
    Nillouise  
       2020-10-21 09:24:27 +08:00
    @laminux29 具体怎么做?自己加 log 编译一个版本出来调试?还是直接编译+断点调试?
    noble4cc
        21
    noble4cc  
    OP
       2020-10-21 10:08:54 +08:00
    @Mirana 是 key 对应的 value 大,一般 key 不会多大
    wiewiewie
        22
    wiewiewie  
       2020-10-21 14:04:32 +08:00
    redis 6 呢?
    salaryfly
        23
    salaryfly  
       2020-10-21 16:04:54 +08:00
    简短的说一下:
    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
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1065 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 20:28 · PVG 04:28 · LAX 12:28 · JFK 15:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.