Redis系列:神器Redis的性能及优化探究

分析Redis性能主要考虑两个问题:

  • 1、Redis为什么这么快 优 化 点 \color{red}{优化点}
  • 2、Redis怎么用能更快 注 意 点 \color{red}{注意点}
  • 3、Redis如何预防问题和修复问题 监 控 点 \color{red}{监控点}

1、分析Redis为什么这么快,我们从以下几方面去分析:

2、分析Redis怎么用能更快,我们从以下几方面去分析:

3、关于Redis使用时如何预防、排查和修复问题,从以下几方面去分析:

1.1、网络层和操作系统层


  • 网络层

    • Redis选取了一种比较优秀的IO模型:epoll,其相对于之前的select模型、poll模型,多出来三个优点,具体见博客:IO多路复用的三种机制Select,Poll,Epoll
      • 优化点1.1.1:使用红黑树结构,一来句柄的最大限制没有了,二来方便了句柄新增、查找和删除。
      • 优化点1.1.2:操作方式由遍历转换成回调,极大的提升了IO效率。
      • 优化点1.1.3:回调方式新增边缘触发,可以理解为优先级高的触发方式,
      • 优化点1.1.4:fd拷贝问题由每次询问就全量复制,修改为增量拷贝。
  • 操作系统层

    • 优化点1.1.5:Redis使用单线程,避免了多线程切换导致的资源和时间消耗,但是这一点不完全属于优化点,针对整个消息流而言,瓶颈并不在CPU,就好像自来水流量小(网络IO),增加接水的人(线程)并不能增大水量,另外要注意:
      • Redis 的单线程指的是 Redis 的网络 IO 以及键值对指令读写是由一个线程来执行的。
      • 整个Redis运行过程中不止一个线程,仅仅是用于IO的是单线程,后续6.0页增加了多线程。
      • 即使是单线程的Redis,也可以通过多起Redis服务,搭建主从、读写分离等方式充分利用多核CPU。
      • 多线程的问题:
        • 多线程的创建和销毁,会带来一定的系统开销
        • 多线程的切换,会带来系统开销(CPU保存上下文)
        • 多线程的竞争,会带来加解锁的性能问题和死锁问题。

1.2、内存及数据结构


  • 内存

    • 设置内存
      • 在配置文件redis.conf 中配置一行 maxmemory xxx 即可
      • 或者通过 config set 命令在运行时动态配置 Redis 的内存大小
    • Redis内存回收策略
      • 定时删除
        • 对每个key新建一个监视器,过期就删除(相当耗费CPU,不采用)
      • 定期删除+随机
        • 每隔一段时间,随机抽取若干个key,若过期,则删除
      • 惰性删除
        • 当访问的时候判断是否过期,过期就删除,重新去数据库取值
    • Redis的Key过期策略
      • 1.volatile-lru: 在所有带有过期时间的 key 中使用 LRU 算法淘汰数据;
      • 2.alkeys-lru: 在所有的 key 中使用最近最少被使用 LRU 算法淘汰数据,保证新加入的数据正常;
      • 3.volatile-random: 在所有带有过期时间的 key 中随机淘汰数据;
      • 4.allkeys-random: 在所有的 key 中随机淘汰数据;
      • 5.volatile-ttl: 在所有带有过期时间的 key 中,淘汰最早会过期的数据;
      • 6.noeviction: 不回收,当达到最大内存的时候,在增加新数据的时候会返回 error,不会清除旧数据,这是 Redis 的默认策略;
    • Key过期策略如何被触发:新增数据时,Redis 会检查内存的使用情况,如果已经超过的最大限制,就是根据配置的内存淘汰策略去淘汰相应的 key,从而保证新数据正常添加
    • 参考博客:Redis的内存回收策略和Key过期策略
  • 数据结构

    • 数据结构上的优化主要是考虑数据存取的时间复杂度,是一种用空间换时间的做法
    • 优化点1.2.1:以跳表为代表的数据结构:数组方便查找,不利于新增,链表利于新增,不利于查找,于是Redis底层实现了跳表,一种可以折半查找的双向链表,增删改查都快。
      • 注意到:在使用单向链表实现跳表的实践中发现,当数据从小到大排序时,按照从大到小插入,效率极慢,但是如果是双向链表,就可以很好解决这个问题。
      • 跳表的实现:Redis底层数据结构:跳表的JAVA实现
    • 优化点1.2.2:以SDS为代表的简单动态字符串结构:
      • O(1)时间内获取字符串长度。
      • 字符串修改时,首先检查字符数组的长度,不够进行动态扩充,防止字符串溢出(缓冲区溢出)
      • 减少字符串修改带来的内存分配次数:空间预分配和惰性释放
      • 二进制安全:允许识别空字符
      • 参考博客:Redis中的简单动态字符串

1.3、Redis版本更新做了那些优化


  • 多线程
    • 实际上redis一直都是多线程的,除了处理请求流程是单线程,其他的比如AOF等都是多线程异步在做,
    • Redis4.0,引入lazyfree机制,异步释放大内存。
    • Redis6.0,引入多线程完成请求数据的协议解析。

1.4、阿里及其他云公司又做了那些优化


2.1、Redis用于缓存


2.2、防止缓存穿透、缓存击穿、缓存雪崩


  • 缓存雪崩
    • 说明:当大量的缓存数据短期内集中过期或者失效,原本可以从redis中查询到的数据,都需要去数据库中查询,数据库IOPS急速增高。
    • 解决办法:放置key值的时候,使用随机时间。
  • 缓存击穿
    • 说明:某些热点数据扛住了大并发的请求,当这些数据一旦失效,瞬间请求就会压到数据库,类似一种击穿redis的效果。
    • 解决办法:将请求进行排队
  • 缓存穿透
    • 说明:数据库中没有的值,缓存也没有,那么每次请求就会直接发送到数据库,类似于对数据库发起DDos攻击。
    • 解决办法1:使用布隆过滤器,大概率的拦截下无效请求。
    • 解决办法2:缓存下无效值,且设置过期时间,在过期时间内可以限制住这些无效请求
    • 解决办法3:对无效值的发起IP进行记录,对于多次发起相同无效值的IP进行黑名单。

2.3、冷热数据分离


3.1、Redis监控


3.2、Redis故障排查


3.3、Redis故障恢复


  • 通过AOF/RDB进行恢复
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值