业务层面和运维层面优化你的Redis


业务层面和运维层面优化你的Redis文章插图
来源:
这篇文章我们就来总结一下 , 在使用Redis时的最佳实践方式 , 主要包含两个层面: 业务层面、运维层面。
由于我之前写过很多UGC后端服务 , 在大量场景下用到了Redis , 这个过程中也踩过很多坑 , 所以在使用过程中也总结了一套合理的使用方法 。
后来做基础架构 , 开发Codis、Redis相关的中间件 , 在这个阶段关注领域从使用层面下沉到Redis的开发和运维 , 更多聚焦在Redis的内部实现和运维过程中产生的各种问题 , 在这块也积累了一些经验 。
下面就针对这两块 , 分享一下我认为比较合理的Redis使用和运维方法 , 不一定最全面 , 也可能与你使用Redis的方法不同 , 但以下这些方法都是我在踩坑之后总结的实际经验 , 供你参考 。
业务层面业务层面主要是开发人员需要关注 , 也就是开发人员在写业务代码时 , 如何合理地使用Redis 。 开发人员需要对Redis有基本的了解 , 才能在合适的业务场景使用Redis , 从而避免业务层面导致的延迟问题 。
在开发过程中 , 业务层面的优化建议如下:

  • key的长度尽量要短 , 在数据量非常大时 , 过长的key名会占用更多的内存
  • 一定避免存储过大的数据(大value) , 过大的数据在分配内存和释放内存时耗时严重 , 会阻塞主线程
  • Redis 4.0以上建议开启 lazy-free 机制 , 释放大value时异步操作 , 不阻塞主线程
  • 建议设置过期时间 , 把Redis当做缓存使用 , 尤其在数量很大的时 , 不设置过期时间会导致内存的无限增长
  • SORT SINTER SINTERSTORE ZUNIONSTORE ZINTERSTORE
  • 查询数据时 , 一次尽量获取较少的数据 , 在不确定容器元素个数的情况下 , 避免使用 LRANGE key 0 -1,ZRANGE key 0 -1 这类操作 , 应该设置具体查询的元素个数 , 推荐一次查询100个以下元素
  • 写入数据时 , 一次尽量写入较少的数据 , 例如 HSET key value1 value2 value3..., 控制一次写入元素的数量 , 推荐在100以下 , 大数据量分多个批次写入
  • MGET/MSET GET/SET HMGET/MHSET HGET/HSET pipeline
  • 禁止使用 KEYS 命令 , 需要扫描实例时 , 建议使用 SCAN, 线上操作一定要控制扫描的频率 , 避免对Redis产生性能抖动
  • 避免某个时间点集中过期大量的key , 集中过期时推荐增加一个随机时间 , 把过期时间打散 , 降低集中过期key时Redis的压力 , 避免阻塞主线程
  • 根据业务场景 , 选择合适的淘汰策略 , 通常随机过期要比LRU过期淘汰数据更快
  • 使用连接池访问Redis , 并配置合理的连接池参数 , 避免短连接 , TCP三次握手和四次挥手的耗时也很高
  • 只使用 db0, 不推荐使用多个db , 使用多个db会增加Redis的负担 , 每次访问不同的db都需要执行 SELECT 命令 , 如果业务线不同 , 建议拆分多个实例 , 还能提高单个实例的性能
  • 读的请求量很大时 , 推荐使用读写分离 , 前提是可以容忍从节数据更新不及时的问题
  • 写请求量很大时 , 推荐使用集群 , 部署多个实例分摊写压力
运维层面运维层面主要是DBA需要关注的 , 目的是合理规划Redis的部署和保障Redis的稳定运行 , 主要优化如下: