Key 与 Value 设计原则

最近更新时间: 2024-10-17 17:10:00

Key设计原则

设计合理的 Key,有助于保证数据库的性能。

Key 命名原则

Redis Key命名需具有可读性及可管理性,不建议使用含义不清的Key以及特别长的Key名。

  • 简洁性:保证语义的前提下,可以适当缩短key的长度,当key较多时,key占用的内存空间也不容忽视,例如:cx:cxdb:cxdb_user_info:000110011可简化为cx:cxdb:user:000110011

  • 命名规则:以英文字母开头,命名中只能出现大小写字母、数字、竖线、下划线、英文点号(.)和英文半角冒号(:)。

  • 按照语义分割:不同业务逻辑含义使用英文半角冒号(:)分割,同一业务逻辑含义段的单词之间使用英文半角点号 (.)分割,用来表示一个完整的语义。

  • 可读性:key名称以key所代表的value类型结尾,以提高可读性。例如:user:basic.info:userid:string。

  • 不使用过大的key名称:key名称过大也会占用一定的内存空间。

  • 禁止包含特殊字符:例如:\ 、*、 ?、 {}、 []、 ()、 空格、单双引号和转义字符等,如果key中存在特殊字符,可能会导致key无法检索或检索失败。

Key生命周期准则

建议使用 expire 设置过期时间,控制 Key 的生命周期。例如:

> set cx:cxdb:user:000110011 xiaoming

> expire cx:cxdb:user:000110011 3600 # 设置 Key 一小时后过期

  • 如果条件允许可以打散过期时间,防止集中过期。

  • 对于没有设置过期的数据,重点关注 idletime。idletime非常大时进行清理。例如,执行> object idletime cx:cxdb:user:000110011

    回显信息如下:

    :(integer) 150039 # 这里表示key有150039秒未被访问过

  • 当一个key有1个月以上未被访问过,则可以认定为冷数据,并进行清理。

Value 设计原则

拒绝 Big Key

大 Key 具体表现为 Redis 中的 Key 对应的 Value 很大,占用 Redis 空间比较大,本质上是大 Value 问题。对于 Redis 中不同的数据结构类型,常见示例如下所示。

  • 对于 String 类型的 Value 值,值超过 10MB(数据值太大)。

  • 对于 Set 类型的 Value 值,含有的成员数量为 10000 个(成员数量多)。

  • 对于 List 类型的 Value 值,含有的成员数量为 10000 个(成员数量多)。

  • 对于 Hash 格式的 Value 值,含有的成员数量 1000 个,但所有成员变量的总 Value 值大小为 1000MB(成员总的体积过大)。

Big key很容易造成慢查询,阻塞其他的请求。同时,也会对网卡造成负担。为防止产生大 Key,设计 Value 时,建议参考如下建议。

  • 建议 String 类型控制在10KB以内;hash、list、set、zset元素个数不要超过5000。

  • 若非必须,不要使用 del 删除大 Key。

  • 对于非字符串的大 Key,建议使用hscan、sscan、zscan渐进式删除。

  • 防止大 Key过期时间自动删除问题。

    例如一个200万的zset设置1小时过期,会触发 del 操作,造成阻塞。

合理选择数据类型

  • Redis提供了多种不同的数据库类型,包括字符串、哈希表、列表、集合和有序集合等。选择合适的数据库类型可以提高Redis的性能和可靠性。

    • 字符串类型:适用于存储简单的字符串数据,例如配置信息、计数器等。如果需要存储二进制数据,可以使用Redis的二进制安全字符串类型。

    • 哈希表类型:适用于存储多个字段和值的数据,例如用户信息、商品信息等。哈希表可以节省内存空间,并且可以方便地进行批量操作。

    • 列表类型:适用于存储有序的元素集合,例如消息队列、任务列表等。列表可以在两端进行插入和删除操作,并且可以使用Redis提供的多种操作命令来操作列表。

    • 集合类型:适用于存储无序的元素集合,例如标签列表、好友列表等。集合可以进行并集、交集、差集等操作,并且可以使用Redis提供的多种操作命令来操作集合。

    • 有序集合类型:适用于存储有序的元素集合,例如排行榜、投票列表等。有序集合可以按照分值进行排序,并且可以使用Redis提供的多种操作命令来操作有序集合。

  • 合理控制和使用数据结构内存编码优化配置,例如ziplist是一种特殊的数据结构,它可以将小型列表、哈希表和有序集合存储在一个连续的内存块中,从而节省了内存空间。但是,由于ziplist没有索引,因此在对ziplist进行查找、插入或删除操作时,需要进行线性扫描,这可能会导致性能下降。在实际应用中,应该根据具体情况来决定是否使用ziplist。如果数据量较小且需要频繁进行遍历操作,那么使用ziplist可能是一个不错的选择。但是,如果数据量较大且需要频繁进行插入、删除或查找操作,那么使用ziplist可能会影响性能,应该考虑使用其他数据结构来代替。

  • 此外,如果一个Key有多个属性,可以考虑使用HashMap类型来代替String类型。HashMap是Redis中的一种键值对存储数据结构,可以用于存储多个字段和值。在Redis中,可以使用HSET命令将多个字段和值存储在一个哈希表中,然后使用HGET命令获取指定字段的值。如果使用String类型来存储多个属性,则需要使用特定的分隔符将不同的属性值拼接成一个字符串,这样会使得操作复杂,并且可能会浪费内存空间。

反面示例

set user:1:name tom

set user:1:age 19

set user:1:favor football

正面示例

hmset user:1 name tom age 19 favor football