替你踩过Redis缓存的坑,奉上使用规范和监控方法( 二 )


继续跟进JedisConnection代码 , 当选择库大于1时 , 会有select db操作 。 如果一直使用0库是不需要额外执行切库命令的 。 知道了第一个切库select 1的地方 , 那么select 0是哪来的呢?
替你踩过Redis缓存的坑,奉上使用规范和监控方法文章插图
其实客户端使用Redis也会是要释放链接的 , 只不过RedisTemplate已经帮我们自动释放了 , 让我们再回到一开始RedisTemplate执行execute(...)方法的地方 。
替你踩过Redis缓存的坑,奉上使用规范和监控方法文章插图
下面还是RedisConnectionUtils.java , 执行链接关闭的代码 。
替你踩过Redis缓存的坑,奉上使用规范和监控方法文章插图
按代码注释的意思 , 如果选择库编号不为0 , spring-data-redis框架每次都会执行重置select 0!
替你踩过Redis缓存的坑,奉上使用规范和监控方法文章插图
笔者在vivo商城业务中 , 商品详情页接口经过上面的调优 , 性能提高了3倍多 。
进一步验证数据库切换至少影响性能3倍左右(视具体业务而定) 。
Rediscluster集群数据库 , 默认0库 , 无法选择其他数据库 , 也就避免了这个问题 。
5、当心时间复杂度o(n)Redis命令
Redis是单线程的 , 所以线程安全的 。
Redis使用非阻塞IO , 并且大部分命令的时间复杂度O(1) 。
使用高耗时的命令是非常危险的 , 会占用唯一的一个线程的大量处理时间 , 导致所有的请求都被拖慢 。
例如:获取所有set集合中的元素 smembers myset , 返回指定Hash中所有的member , 时间复杂度O(N) 。
缓存的Value集合变大 , 当高并接口请求时 , 会从Redis读取相关数据 , 每个请求读取的时间变长 , 不断的叠加 , 导致出现热点KEY情况 , Redis某个分片处于阻塞 , CPU使用率达到100% 。
6、缓存热key
在Redis中 , 访问频率高的key称为热点key , 当某一热点key的请求到Server主机时 , 由于请求量特别大 , 导致主机资源不足 , 甚至宕机 , 影响正常的服务 。
热key问题的产生 , 有如下两种原因:

  • 用户消费的数据远大于生产的数据 , 比如热卖商品或秒杀商品、热点新闻、热点评论等 , 这些典型的读多写少的场景会产生热点问题;
  • 请求分片集中 , 超过单Server的性能极限 , 比如 固定名称key , 哈希落入一台Server , 访问量极大的情况 , 超过Server极限时 , 就会导致热点Key问题的产生 。
那么在实际业务中 , 如何识别到热点key呢?
  • 凭借业务经验 , 进行预估哪些是热key;
  • 客户端统计收集 , 本地统计或者上报;
  • 如果服务端有代理层 , 可以在代理层进行收集上报 。
当我们识别到热key , 如何解决热key问题?
  • Redis集群扩容:增加分片副本 , 均衡读流量;
  • 进一步对热key进行散列 , 比如将一个key备份为key1,key2……keyN , 同样的数据N个备份 , N个备份分布到不同分片 , 访问时可随机访问N个备份中的一个 , 进一步分担读流量;
  • 使用二级缓存 , 即本地缓存 。
当发现热key后 , 将热key对应数据首先加载到应用服务器本地缓存中 , 减少对Redis的读请求 。
五、Redis规范
1、禁止使用非database 0
说明:
【替你踩过Redis缓存的坑,奉上使用规范和监控方法】Redis-standalone架构 , 禁止使用Redis中的其他database 。
原由:
  • 为以后业务迁移 Redis Cluster 保持兼容性;
  • 多个 database 用 select 切换时 , 更消耗CPU资源;
  • 更易自动化运维管理 , 如 scan/dbsize 命令只用于当database;
  • 部分 Redis Clients 因线程安全问题 , 不支持单实例多 database 。
2、Key设计规范
按业务功能命名key前缀 , 防止key冲突覆盖 , 推荐 用冒号分隔 , 例如 , 业务名:表名:id: , 如 live:rank:user:weekly:1:202003 。
Key的长度小于30个字符 , Key名字本身是String对象 , Redis硬编码限制最大长度512MB 。
在Redis缓存场景 , 推荐Key都设置TTL值 , 保证不使用的Key能被及时清理或淘汰 。
Key设计时禁止包含特殊字符 , 如空格、换行、单双引号以及其他转义字符 。
3、Value设计规范
单个Value大小必须控制10KB以内 , 单实例键个数过大 , 可能导致过期键的回收不及时 。
set、hash、list等复杂数据类型 , 要尽量降低数据结构中的元素个数 , 建议个数不要超过1000 。
4、关注命令时间复杂度