zoukankan      html  css  js  c++  java
  • 代码实测:给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获取执行的总时长:

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

     

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

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

     

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

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

    第一组测试数据

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

    第二组测试数据

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

    第三组测试数据

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

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

     

    当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算法及应用场景

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

     

    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以内,实际也和元素字节数有关)。
  • 相关阅读:
    Java并发容器总结
    ReentrantLock源码分析
    webpack插件之webpack-dev-server
    webpack插件之htmlWebpackPlugin
    webpack配置之webpack.config.js文件配置
    webpack的安装和运行
    webpack安装大于4.x版本(没有配置webpack.config.js)
    webpack安装低于4版本(没有配置webpack.config.js)
    什么是webpack以及为什么使用它
    webpack前置知识2(JavaScript项目初始化)
  • 原文地址:https://www.cnblogs.com/CQqfjy/p/12254903.html
Copyright © 2011-2022 走看看