Key 与 Value 设计原则

最近更新时间:2023-05-11 16:56:18

我的收藏

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