⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 jianshu.com/p/932b69c8aa2f 「阿飞的博客」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

Key命名设计:可读性、可管理性、简介性

规范建议使用冒号即:进行分割拼接,因为很多Redis客户端是根据冒号分类的。比如有几个Key:apps:app:1、apps:app:2和apps:app:3。Redis Desktop Manager能自动归类到apps目录下。如下图所示:

Redis Desktop Manager

Value设计:拒绝bigkey

规范建议String类型的Value控制在10KB范围以内。这是因为Redis随着Value不断增长,在超过10KB后,有一个非常奇妙的性能拐点,如下图所示(图片来自Redis官网:http://redis.cn/topics/benchmarks.html):

Redis_Data_size

假设内网带宽是千兆网卡,即1000MB。假设你的Redis中有一个大Key的Value长度是10KB,并且这个Key的QPS是10W,那么这一个Key就会把带宽打满:10KB*100000=1000MB。

控制Key的生命周期:设定过期时间

尽可能对每一个Key都设置过期时间,这个是非常有益处的。否则,你想想一下,半年以后,一年以后,你的Redis集群中有上百G甚至更多的数据,谁都不知道这些数据哪些是有价值的,哪些已经成为垃圾。如果你的每个Key都设置了过期时间,那么就不会出现这个问题了。集群在运行过程中,或自动淘汰那些已经不再使用的垃圾缓存数据。

时间复杂度为O(n)的命令需要注意N的数量

这个建议的意思是,以List类型为例,LINDEX、LREM等命令的时间复杂度就是O(n)。也就是说,随着List中元素数量越来越多,这些命令的性能越来越差。而Redis又是单线程的,如果出现一个慢命令,会导致在这个命令之后执行的命令耗时也会增长,这是使用Redis的大忌。

事实上这也是JDK8为什么要对HashMap进行链条冲突优化:当entry数量不少于64时,如果冲突链表长度达到8,就会将其转成红黑树。因为链表长度越长,性能会越来越差。

禁用命令:KEYS、FLUSHDB、FLUSHALL等

这些命令应该在搭建Redis环境的时候就要禁用掉(在config配置文件中通过rename-command禁用)。FLUSHDB和FLUSHALL这两个命令会清空数据,后果可想而知。

至于KEYS命令,还记得那个由于使用这个命令导致几百万损失的案例嘛?而且,这个命令的不当使用导致的损失,会随着你的业务并大越大价值越大而导致损失越大:

KEYS引发的灾难

推荐使用批量操作提升操作效率

批量命令主要分为两类,原生命令和非原生命令:

  • 原生命令包括:例如mget、mset、hmget、hmset、LPUSH key value集合等。
  • 非原生命令包括:Pipeline。

合理使用这些命令对操作性能提升是极其巨大的,尤其在单机Redis或者Sentinel模式下。因为这两种架构不涉及跨Slot,Redis集群性能也有提升,但是使用会受到一些限制,例如不支持跨Slot的操作。

当然批量虽好,但不要贪多。俗话说的好,贪多嚼不烂。一般不要超过1000,具体限制还与操作数据大小有关。

monitor命令控制使用时间

monitor命令一般是用来观察redis服务端都在执行哪些命令并实时输出。例如在其他redis-cli中执行两个set命令,在monitor中监控结果如下:

afeiMacBook-Pro:redis-3.2.11 afei$ src/redis-cli monitor
OK
1573915193.053188 [0 127.0.0.1:55357] "COMMAND"
1573915197.087383 [0 127.0.0.1:55357] "set" "name" "afei"
1573915217.938838 [0 127.0.0.1:55357] "set" "公 众 号" "阿飞的博客"

之所以规范建议控制monitor命令的使用时间,是因为随着monitor命令执行时间越来越长,会导致越来越多的数据积压在输出缓冲区,从而导致输出缓冲区占用内存越来越大。而且,这种影响会由于Redis并发越高,而更加放大。关于这个问题,美团有一个很经典的案例,感兴趣的同学可以搜索关键词:“美团在REDIS上踩过的一些坑-3.REDIS内存占用飙升”。

写在最后

总而言之,任何一门技术都有利有弊,技术的世界里没有银弹。所以,我们对使用到生产环境的任何一个技术,都要非常熟悉:知道它所擅长的和它的弱点,这样才能结合自己的项目特点,设计出更合理的架构,编写出最合理的代码,不给生产环境造成影响,不给公司带来损失 -- 千万不要成为那个执行KEYS命令导致给公司造成金钱损失的人!

文章目录
  1. 1. Key命名设计:可读性、可管理性、简介性
  2. 2. Value设计:拒绝bigkey
  3. 3. 控制Key的生命周期:设定过期时间
  4. 4. 时间复杂度为O(n)的命令需要注意N的数量
  5. 5. 禁用命令:KEYS、FLUSHDB、FLUSHALL等
  6. 6. 推荐使用批量操作提升操作效率
  7. 7. monitor命令控制使用时间
  8. 8. 写在最后