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

Redis 中 Key 为什么也使用 SDS 而不是 C 字符串呢?

  •  
  •   jay1002008 · 2021-05-21 00:18:46 +08:00 · 3064 次点击
    这是一个创建于 1311 天前的主题,其中的信息可能已经有所发展或是发生改变。

    SDS 类型具有几大优势:

    1. 常数复杂度获取字符串长度
    2. 杜绝缓冲区溢出
    3. 减少修改字符串长度时所需的内存重分配次数
    4. 二进制安全
    5. 兼容部分 C 字符串函数

    但是,Redis Key 不需要修改,所以大部分优势都不存在了,为什么还需要 SDS 类型呢,使用 C 字符串不香吗?

    16 条回复    2021-05-24 10:25:39 +08:00
    CEBBCAT
        1
    CEBBCAT  
       2021-05-21 00:33:02 +08:00
    我个人觉得,二进制安全就已经很诱人了。另外搜到一篇博客,一起贴上来:

    https://redisbook.readthedocs.io/en/latest/internal-datastruct/sds.html
    ebingtel
        2
    ebingtel  
       2021-05-21 09:22:54 +08:00
    "Redis Key 不需要修改", 应用层面可以这么说……但是 redis 内部进行管理的话,应该不是, 比如 dict 进行 rehash
    GrayXu
        3
    GrayXu  
       2021-05-21 10:29:19 +08:00
    因为 redis key 并不是不需要修改的。
    jay1002008
        4
    jay1002008  
    OP
       2021-05-21 12:14:49 +08:00
    @GrayXu 比如哪个场景?请教
    jay1002008
        5
    jay1002008  
    OP
       2021-05-21 12:15:30 +08:00
    @ebingtel dict rehash 的时候,key 也需要 update 吗?是哪个步骤呢?请教下哈
    ebingtel
        6
    ebingtel  
       2021-05-21 13:44:37 +08:00
    @jay1002008 不是说要改 而是说在不改的情况下,用到你原文提到的 sds 优势……比如 dict.c 里面:compareCallback 的函数 你可以看看
    ebingtel
        7
    ebingtel  
       2021-05-21 13:46:23 +08:00
    @jay1002008 或者在源码里面 搜一下 sds 之类的关键字 就能看到很多场景需要了
    ruanimal
        8
    ruanimal  
       2021-05-21 15:19:06 +08:00
    因为 sds 的内存是复用的,也就是需要修改
    jay1002008
        9
    jay1002008  
    OP
       2021-05-21 16:32:10 +08:00
    @ebingtel
    看了下 dict.c 中 compareCallback 函数,具体如下:

    int compareCallback(void *privdata, const void *key1, const void *key2) {
    int l1,l2;
    DICT_NOTUSED(privdata);

    l1 = strlen((char*)key1);
    l2 = strlen((char*)key2);
    if (l1 != l2) return 0;
    return memcmp(key1, key2, l1) == 0;
    }

    里面用到了 strlen 和 memcmp 两个 C 函数,sds 可以支持,但 c 字符串也可以支持,所以还是不太理解这个场景。

    另外,sds 使用的场景确实有,但 key 使用 sds 的必要场景,感觉还是没有见到。
    jay1002008
        10
    jay1002008  
    OP
       2021-05-21 16:33:55 +08:00
    @ruanimal
    我的问题是:redis 存储键值对,Key 也使用 sds,感觉没啥必要。--!
    ebingtel
        11
    ebingtel  
       2021-05-21 17:51:04 +08:00
    @jay1002008 咱俩的版本不一样:

    int compareCallback(void *privdata, const void *key1, const void *key2) {
    int l1,l2;
    DICT_NOTUSED(privdata);

    l1 = sdslen((sds)key1);
    l2 = sdslen((sds)key2);
    if (l1 != l2) return 0;
    return memcmp(key1, key2, l1) == 0;
    }
    ……
    sanggao
        12
    sanggao  
       2021-05-21 18:38:56 +08:00
    redis 有 rename 这个函数啊,这个就是供用户修改 key 的
    jay1002008
        13
    jay1002008  
    OP
       2021-05-21 19:26:32 +08:00
    @ebingtel
    呃。好像是的呢。不过看到你的版本,我理解了。
    jay1002008
        14
    jay1002008  
    OP
       2021-05-21 19:27:10 +08:00
    @sanggao
    哦,是的呢,都不记得有这个命令了。rename 的时候,这个似乎最方便了。
    3Q
    ruanimal
        15
    ruanimal  
       2021-05-24 09:54:34 +08:00
    @jay1002008 因为 sds 不只是 key 在用, 内部所以用到字符串的地方基本都是用的 sds,你看下源码就知知道了
    jay1002008
        16
    jay1002008  
    OP
       2021-05-24 10:25:39 +08:00
    @ruanimal 可能我没有表达清楚,我的问题是:为什么 key 也使用 sds,而不是“内部用到字符串的地方”为什么使用 sds 。
    问题的解答 @sanggao 举的例子最体验了直接原因哈。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2665 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 07:46 · PVG 15:46 · LAX 23:46 · JFK 02:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.