4.Redis最佳实践

Redis的键值设计:

(1)优雅的key设计 :

  • 遵循基本格式 : [业务名称] : [数据名] : [id]
  • 长度不超过44字节
  • 不包含特殊字符

例如我们的登录业务 , 保存用户信息 , 其key是这样的

imag

优点 :

  • 可读性强
  • 避免key冲突
  • 方便管理
  • 更节省内存 : key 是String 类型, 底层编码包含 int , embstr 和 raw 三种 ,
    • embstr在小于 44字节使用 , 采用连续内存空间 , 内存占用更小 ,
    • 如果超过44字节 , 就会使用 raw 编码方式 , 通过指针指向内存地址 , 这会在性能上造成一定的影响

在redis中 , 使用 object encoding key , 可以看到key的类型是什么

注意:

  • 如果redis版本是低于4.0的版本 , 那么限制就是39个字节

(2)Bigkey问题:

Bigkey通常以key的大小和key中成员的数量来判断 , 例如

  • key本身的数据量过大 : 一个String类型的key , 它的值为5MB
  • key中的成员数量过多 : 一个Zset类型的key , 它的成员数量为10000个
  • key中的成员的数据量过大 : 一个hash类型的key , 它的成员数量虽然只有1000个 , 但是这些成员的Value值总大小为100MB

推荐值:

  • 单个key的value小于10kb
  • 对于集合类型的key , 建议元素数量小于1000

redis中提供的可以查询key的内存大小的命令:

MEMORY USAGE KEY

不推荐使用 : 这个命令对于CPU的使用较大


实际操作中我们通过预估即可 :

  1.  STRLEN KEY
    
    

可以查看这个key的value有几个字节

  1. LLEN l2
    

可以查看数组的大小

  • String ==> Strlen
  • hash ==> hlen
  • list ==> llen
  • set ==> scard
  • zset ==> zcard

BigKey的危害:

imag

写数据的时候需要序列化 , 读数据的时候需要反序列化


如何发现BigKey:

  1. redis-cli --bigkeys

    • 利用redis-cli提供的 --bigkeys 参数 , 可以遍历分析所有的key , 并返回key的整体统计信息与,每个数据的Top1 , 的bigkey
  2. scan 扫描 :

    • 自己编程 , 利用scan扫描redis中的所有key , 利用strlen , hlen , 等命令判断key的长度 , (此处不建议使用 MEMORY USAGE)

    • SCAN 光标 : 代表扫描到那个位置了 , 下一次扫描从这个光标开始
      
    • @Test
      void test(){
          String cursor = "0";
          long len = 0;
      
          do {
              //扫描并获取一部分key
              ScanResult<String> result = jedis.scan(cursor);
              // 记录cursor
              cursor = result.getCursor();
              // 获取集合
              List<String> list = result.getResult();
              if (list == null || list.isEmpty()){
                  break;
              }
              // 循环遍历数组
              for (String key : list){
                  // 判断key的类型
                  String type = jedis.type(key);
                  switch(type){
                          //根据不同的key的值 , 来进行不同的操作
                      case "string":
                          len = jedis.strlen(key);
                          maxlen = STR_MAX_LEN;
                          break;
                      case "set": ....
                  }
              }
              if(len > maxlen){
                  sout("长度超过预设计的值 , 打印")
              }
          }
      }
      
  3. 第三方工具 :

    • 利用第三方工具 , 如 Redis-Rdb-Tools 分析 RDB快照文件 , 全面分析内存使用情况
  4. 网络监控 :

    • 自定义工具 , 监控进出Redis的网络数据 , 超出预警值是主动告警

删除bigkey:

Bigkey内存占用较多 , 即便是删除bigkey也需要耗时很长时间 , 导致Redis主线程阻塞 , 引发一系列问题

  • Redis 3.0 及以下版本

    • 如果是集合类型 , 则遍历BigKey的元素 , 先逐个删除子元素 , 最后删除Bigkey

    • HScan , ZScan ,  
      
  • Redis 4.0 以后 ,

    • Redis在4.0后提供了异步删除的命令 , unlink

    • unlink key
      

恰当的数据类型 :

Redis中的hash结构 , 底层使用ziplist , 空间占用小 , 可以灵活访问对象的任意字段 ,

但是 , 如果hash的entry(键值对)数量超过500时 , 会使用哈希表而不是 ziplist , 内存占用较多

  • 可以使用 hash-max-ziplist-entries 命令来查询和修改 , 默认的键值对数量的大小

    • config set hash-max-ziplist-entries 指定的大小
      

注意:

  • String 类型的数据结构 , 底层并没有太多的内存优化 , 在存储key的时候 , 也会存储大量的元数据 , 这会造成数据占用的内存大大提高 ,
  • 所以不能一味的使用String , hash也是存在一定的缺点 ,
  • 所以 , 只有选择最正确的数据结构 , 才能大大优化内存的占用

批处理优化 :

批处理的方案 :

  • 原生的M操作
  • Pipeline批处理操作

M操作 : 是redis的内置操作 , 它会将多组key和value , 作为一个原子操作 ,一次性全执行完 不会有其他操作插队

pipeline : 多个命令之间并不是原子性的 , 会造成其他命令的插队


  • 单个命令传输的时候 :
    • 一次操作的时间是 = 往返的网络时间 + redis操作命令的时间
    • 大量命令的话 , 使用单个命令的话 , 会在网络传输的时间上浪费大量的时间
  • 使用批处理的时候 :
    • 一次可以传输大量的命令 , 减少往返的网络时间的消耗 ,
    • 但是 , 一次批处理中传输太多的命令 , 会导致单次命令占用带宽过多 , 会导致网络阻塞

pipeline :

mset虽然可以批处理 , 但是却只能操作部分的数据类型 , 因此 , 如果对复杂数据类型的批处理需要 , 建议使用Pipeline功能:

// 获取批处理通道
Pipeline pipeline = jedis.pipeline();
// 放入命令到管道 , 这里可以对大部分的数据类型进行操作  
pipeline.set("") // || hset ...
//批量执行 
pipeline.sync(); 

集群下的批处理:

如果MSET和Pipeline这样的批处理需要在一次请求中携带多条命令 , 而此时如果Redis是一个集群 ,那批处理命令的多个key必须落在一个插槽中 , 否则就会导致执行失败

image-20220425155435176

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值