暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

让你的 Redis 起飞的键值设计规范

Dtalk 2021-06-21
4732

作者简介

作者:冀浩东

转转后端存储架构师,数据库存储平台负责人,目前负责转转整体存储系统运营。

业务在使用 Redis 过程中可能会经常遇到各种各样的问题,今天我们先从 Redis 键值对设计的角度出发,看下常见因键值对设计不合理影响的业务一些情况,以及应该如何优化。


本文主要分为以下两部分:

1. key 命名规范

2. value 设计规范


01

key 命名规范

key 的命名规范是非常重要的, 这在海量KV的治理场景下,是一个特别重要的优化点。一个好的命名规范,既可以具体有良好的可管理性,又可以节省内存。

我们先看一个正确且优秀的例子:

    redis> GET regv:uid:100123 
    "zhangsan"

    key 命名模版如下:

    简单解释一下 regv:uid:100123的命名规则:

    • regv:  业务服务名称

    • uid:   字段逻辑含义

    • 100123:  具体业务ID

    该模版依然可以简化,具体如下:

    整体建议使用以上 key 命名模版常规版或者精简版,补充描述信息可以在 [opt] 中添加, {uid}存放对应具体业务ID。

    建议:在描述尽量完整的情况下,优先选择精简版

    我们再看下一些不建议使用的例子:

      // 反例 1 
      redis> SET registryservice:userid:string:100123 "zhangsan"
      OK
      // 反例 2
      redis> SET 6B1B0C32-C2C5-4E48-B6BC-DEFA25E41919 "zhangsan"
      OK
      // 反例 3
      redis> SET "!@#/:$%^&*()+100123" "zhangsan"
      OK
      // 反例 4
      redis> SET "a b c d 100123" "sometext"
      OK

      这些个例子中,

      反例 1key 太长,这个key的长度甚至大于value长度,点是描述信息很明确,缺点就是浪费内存


      反例 2:在反例1的基础上,KEY本身是个UUID,缺点:key 太长、含义无可读性,无法scan


      反例 3:在反例2的基础上,增加了特殊字符,缺点:无可读性,部分场景下会引发业务异常


      反例 4:key 中包含了空格,缺点:无可读性,部分场景下引发业务歧义


      key 不要太长的原因

      先说原因,就是避免内存浪费。

      在 Redis 中 key 就是字符串(String)类型,value 可以是 string、hash、list、set、zset等类型。


      再看下影响 key 内存占用的几个关键数据结构:

      1. redisObject 数据结构:

      这个属于通用数据结构,每个键值对都会包含 redisObject 数据结构。


      2. SDS 数据结构:

      可以回顾一下Redis(String)文章内容:

      Redis 数据结构之字符串 (String)

      3. KEY 过期设置:

        typedef struct redisDb {
        dict *dict; /* The keyspace for this DB */
        dict *expires; /* Timeout of keys with a timeout set */
        dict *blocking_keys; /* Keys with clients waiting for data (BLPOP) */
        dict *ready_keys; /* Blocked keys that received a PUSH */
        dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
        struct evictionPoolEntry *eviction_pool; /* Eviction pool of keys */
        int id; /* Database ID */
        long long avg_ttl; /* Average TTL, just for stats */
        } redisDb;

        关于过期问题,后面的篇幅中会单独细讲,本次不讨论过多细节,其中过期字典中会存放过期的键值对,键为 key 名称,值为对应 key 的数据类型。如果 key 的命名太长,那么此时 key 的内存占用又会再一次增加。

            影响 Redis key 占用内存的因素:

        1. key 的长度,如果过长,内部编码会从 embstr 变为 raw,相对增大了内存开销;

        2. 过期设置


        key 命名规范总结

        1. 以英文字母开头

        2. 建议只是用小写字母、数字、冒号

        3. 不要包含特殊字符

        4. 不通描述信息,需要用冒号分割

        5. key不要太长,能缩写就缩写



        02

        value 设计规范

        1. 禁止上线 bigkey

        bigkey 不仅是导致 Redis阻塞的根源,也是网卡飙高的罪魁祸首,一般建议 value 小于1KB,这个不是硬性指标,应该结合硬件资源、QPS 统一计算。

        2. 善用数据类型

        明确各个数据类型的内部编码,在有高性能需求的情况下,建议使用性能较好的编码方式。

        具体可以参考以下文章:

        Redis 字符串 (String)

        Redis 哈希(Hash)

        Redis 列表(List)

        Redis 集合(Set)

        Redis 有序集合 (Sorted Set)


        3. 压缩数据

        如果数据具备良好的压缩效果,一定要压缩数据,避免出现 bigkey。

        4. 过期设置

        • 建议添加过期时间

        • 避免防止集群过期

        • 如果是 Codis,需要定时清理过期 key



        END

        往期回顾


        Redis 数据结构之集合(Set)

        Redis 数据结构之哈希(Hash)

        Redis 数据结构之列表(List)

        Redis 数据结构之有序集合(Sorted Set)


        文章转载自Dtalk,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论