如何进行Redis性能优化?这一篇就够了( 三 )

  • volatile-lfu:只淘汰访问频率最低、并设置了过期时间 key(4.0+版本支持)
  •  
    一般最常使用的是 allkeys-lru / volatile-lru 淘汰策略 , 它们的处理逻辑是,每次从实例中随机取出一批 key(这个数量可配置) , 然后淘汰一个最少访问的 key,之后把剩下的 key 暂存到一个池子中,继续随机取一批 key,并与之前池子中的 key 比较,再淘汰一个最少访问的 key 。以此往复 , 直到实例内存降到 maxmemory 之下 。
    需要注意的是,Redis 的淘汰数据的逻辑与删除过期 key 的一样,也是在命令真正执行之前执行的,也就是说它也会增加我们操作 Redis 的延迟,而且,写 OPS 越高 , 延迟也会越明显 。
    如何进行Redis性能优化?这一篇就够了

    文章插图
     
    如果此时你的 Redis 实例中还存储了 bigkey , 那么在淘汰删除 bigkey 释放内存时 , 也会耗时比较久 。
    6.fork耗时严重
    当 Redis 开启了后台 RDB 和 AOF rewrite 后 , 在执行时,它们都需要主进程创建出一个子进程进行数据的持久化 。主进程创建子进程,会调用操作系统提供的 fork 函数 。
    而 fork 在执行过程中,主进程需要拷贝自己的内存页表给子进程,如果这个实例很大,那么这个拷贝的过程也会比较耗时 。
    而且这个 fork 过程会消耗大量的 CPU 资源,在完成 fork 之前 , 整个 Redis 实例会被阻塞?。?无法处理任何客户端请求 。
    如果此时你的 CPU 资源本来就很紧张,那么 fork 的耗时会更长,甚至达到秒级,这会严重影响 Redis 的性能 。
    那如何确认确实是因为 fork 耗时导致的 Redis 延迟变大呢?
    你可以在 Redis 上执行 INFO 命令,查看 latest_fork_usec 项,单位微秒 。
    # 上一次 fork 耗时,单位微秒latest_fork_usec:59477这个时间就是主进程在 fork 子进程期间 , 整个实例阻塞无法处理客户端请求的时间 。
    如果你发现这个耗时很久,就要警惕起来了 , 这意味在这期间,你的整个 Redis 实例都处于不可用的状态 。
    除了数据持久化会生成 RDB 之外,当主从节点第一次建立数据同步时,主节点也创建子进程生成 RDB , 然后发给从节点进行一次全量同步,所以 , 这个过程也会对 Redis 产生性能影响 。
    如何进行Redis性能优化?这一篇就够了

    文章插图
     
    7.开启内存大页
    除了上面讲到的子进程 RDB 和 AOF rewrite 期间,fork 耗时导致的延时变大之外 , 这里还有一个方面也会导致性能问题 , 这就是操作系统是否开启了内存大页机制 。
    什么是内存大页?
    我们都知道,应用程序向操作系统申请内存时,是按内存页进行申请的,而常规的内存页大小是 4KB 。
    linux 内核从 2.6.38 开始,支持了内存大页机制 , 该机制允许应用程序以 2MB 大小为单位,向操作系统申请内存 。
    应用程序每次向操作系统申请的内存单位变大了,但这也意味着申请内存的耗时变长 。
    这对 Redis 会有什么影响呢?
    当 Redis 在执行后台 RDB,采用 fork 子进程的方式来处理 。但主进程 fork 子进程后 , 此时的主进程依旧是可以接收写请求的,而进来的写请求,会采用 Copy On Write(写时复制)的方式操作内存数据 。
     
    也就是说,主进程一旦有数据需要修改,Redis 并不会直接修改现有内存中的数据 , 而是先将这块内存数据拷贝出来,再修改这块新内存的数据 , 这就是所谓的「写时复制」 。
    写时复制你也可以理解成 , 谁需要发生写操作,谁就需要先拷贝,再修改 。
    这样做的好处是,父进程有任何写操作,并不会影响子进程的数据持久化(子进程只持久化 fork 这一瞬间整个实例中的所有数据即可,不关心新的数据变更,因为子进程只需要一份内存快照,然后持久化到磁盘上) 。
    但是请注意 , 主进程在拷贝内存数据时,这个阶段就涉及到新内存的申请 , 如果此时操作系统开启了内存大页,那么在此期间,客户端即便只修改 10B 的数据,Redis 在申请内存时也会以 2MB 为单位向操作系统申请,申请内存的耗时变长,进而导致每个写请求的延迟增加,影响到 Redis 性能 。
    同样地,如果这个写请求操作的是一个 bigkey,那主进程在拷贝这个 bigkey 内存块时,一次申请的内存会更大 , 时间也会更久 。可见,bigkey 在这里又一次影响到了性能 。


    推荐阅读