redis key不能包含_代码实测:给redis中的key取一个正确的名字多么重要

redis对写入的key长度有限制吗?

太长的key对性能有影响吗?

key越长对性能影响越大?

如何评估键长度对性能的影响?

talk is cheap, show me the code!

今天我们一起用代码来验证一下key的长度对redis读取key的性能影响。

网络环境:本地

内存:8G

redis版本:redis-5.0.7

实验代码如下,读写1000次长度为16、128、512、1024、2048、4096、9012、20000、100000长度的key获取执行的总时长:

681642058518761497ba0601ee600abc.png

随机生成指定长度的字符串方法如下:

9ee4164b02fbde20b8f91d0a4257aca1.png

运行main方法三次,数据表现基本一致,下图是运行输出的三组数据:

15aa0733b7bdf5fab4314916584fbec6.png

第一组测试数据

c58f8a8af0bcc8d2051eda9260889ee6.png

第二组测试数据

d51aa2eca142c7edeab7316e31332bb7.png

第三组测试数据

根据上面三组数据生成的柱状图如下:

c31f0805cb73d9d95e95a40a3b86f677.png

当key的长度不超过1024即1kb的长度的时候,基本上对性能不造成影响,但是一旦超过1024长度,随着key长度的增加,耗时也会随之增加。

所以,key长度对redis读写性能的影响是当key长度超过1024字节!因此我们在实际开发过程中可以根据自己的key长度预估对redis是否存在性能影响。

在实际业务开发中,基本上大家的key不会超过1024字节,因此可以在命名的时候,尽量取一些能见名知义的key,不必刻意为了缩短key长度而降低key的可读性

当有这种key就必须特别长的时候,或者不确定是否超过1024字节,我们可以对key做一次hash后取哈希值作为redis的key,这样就可以大幅提高redis的性能了。这里推荐大家使用Murmurhash算法,算法详情见我的文章:MurmurHash算法及应用场景

26fe09829f1c9568d1fd5d0cce44797a.png

redis官网对key的描述有如下的一些规则

非常长的key是不推荐的。一个1024 bytes是一个非常坏的注意,不仅仅是因为内存浪费,更是因为在数据集中搜索对比的时候需要耗费更多的成本。当要处理的是匹配一个非常大的值,从内存和带宽的角度来看,使用这个值的hash值是更好的办法(比如使用SHA1)。 特别短的key通常也是不推荐的。在写像u100flw这样的键的时候,有一个小小的要点,我们可以用user:1000:followers代替。可读性更好,对于key对象和value对象增加的空间占用与此相比来说倒是次要的。当短的key可以很明显减少空间占用的时候,你的工作就是找到正确的平衡。 尝试去固定一个schema。比如object-type:id是一个好主意,-和.通常用于多个字符的域,就像comment:1234:reply.to,或者comment:1234:reply-to。 最大的key允许512MB

redis的一些开发规范

key命名设计

(1)【建议】: 可读性和可管理性 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id
(2)【建议】: 简洁性 保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视,例如:U_O_P_HS:#userId代表用户已经购买的商品Id的hash存储
(3)【强制】:不要包含特殊字符反例:包含空格、换行、单双引号以及其他转义字符

value设计

(1)【强制】:拒绝bigkey(防止网卡流量、慢查询)string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000。反例:一个包含200万个元素的list。非字符串的bigkey,不要使用del删除,使用hscan、sscan、zscan方式渐进式删除,同时要注意防止bigkey过期时间自动删除问题(例如一个200万的zset设置1小时过期,会触发del操作,造成阻塞,而且该操作不会不出现在慢查询中(latency可查)),查找方法和删除方法
(2)【推荐】:选择适合的数据类型。例如:实体类型(要合理控制和使用数据结构内存编码优化配置,例如ziplist,但也要注意节省内存和性能之间的平衡)正例:hmset user:1 name tom age 19 favor football
(3).【推荐】:控制key的生命周期,redis不是垃圾桶。 建议使用expire设置过期时间(条件允许可以打散过期时间,防止集中过期),不过期的数据重点关注idletime。

命令使用

【推荐】O(N)命令关注N的数量 例如hgetall、lrange、smembers、zrange、sinter等并非不能使用,但是需要明确N的值。有遍历的需求可以使用hscan、sscan、zscan代替。
【推荐】禁用命令 禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用scan的方式渐进式处理。
【推荐】使用批量操作提高效率原生命令:例如mget、mset。 非原生命令:可以使用pipeline提高效率。 但要注意控制一次批量操作的元素个数(例如500以内,实际也和元素字节数有关)。

实际开发中,大家还有哪些redis的使用经验呢?欢迎大家评论区讨论,一起交流,共同学习!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想监听 Redis 的 `__keyevent@0__:expired` 主题下某个特定 key 的过期事件,可以按照以下步骤进行操作: 1. 将 key 值拼接到主题,形成一个新的主题,例如 `__keyevent@0__:expired:yourkey`。 2. 在代码订阅这个新的主题,例如 `new PatternTopic("__keyevent@0__:expired:yourkey")`。 3. 当 Redis 的 `yourkey` 过期时,就会触发该主题的消息,从而执行消息监听器的回调方法。此时你可以在回调方法编写对应的业务逻辑。 下面是一段示例代码: ```java public class RedisKeyExpirationListener implements MessageListener { private final String key; public RedisKeyExpirationListener(String key) { this.key = key; } @Override public void onMessage(Message message, byte[] pattern) { String expiredKey = message.toString(); if (expiredKey.equals(key)) { // 处理 key 过期事件的业务逻辑 System.out.println("Key " + key + " has expired."); } } // 订阅指定 key 的过期事件 public void subscribeKeyExpiration(Jedis jedis) { jedis.subscribe(this, new PatternTopic("__keyevent@0__:expired:" + key)); } } ``` 在上面的代码,我们定义了一个 `RedisKeyExpirationListener` 类,它将监听 Redis 指定 key 的过期事件。在 `subscribeKeyExpiration` 方法,我们订阅了 `__keyevent@0__:expired:yourkey` 主题,其 `yourkey` 为我们要监听的 key 值。在 `onMessage` 方法,我们判断接收到的过期事件是否为我们要监听的 key,如果是,则执行相应的业务逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值