J6:Redis如何避免异步阻塞,CPU对redis的影响

#

1. 和客户端交互时的阻塞点

  • Redis通过IO多路复用,避免了主线程等待请求(网络IO不是阻塞原因)
  • 复杂度高的怎删改查操作会阻塞Redis
    • 集合全量查询操作(HGETALL,SMEMBERS),聚合统计
    • bigkey删除(释放的内存快放入空闲内存块链表)
    • 清空数据库

2. 和磁盘交互时的阻塞点

  • AOF日志同步写

3. 主从节点交互时的阻塞点

  • 加载 RDB 文件就成为了 Redis 的第五个阻塞点。

4. 异步的子线程机制

  • Redis 主线程启动后,会使用操作系统提供的 pthread_create 函数创建 3 个子线程,分别由它们负责 AOF 日志写操作、键值对删除以及文件关闭的异步执行。
  • 主线程通过一个链表形式的任务队列和子线程进行交互。当收到键值对删除和清空数据库的操作时,主线程会把这个操作封装成一个任务,放入到任务队列中,然后给客户端返回一个完成信息,表明删除已经完成。(惰性删除)
  • 当 AOF 日志配置成 everysec 选项后,主线程会把 AOF 写日志操作封装成一个任务,也放到任务队列中。后台子线程读取任务后,开始自行写入 AOF 日志,这样主线程就不用一直等待 AOF 日志写完了。
    在这里插入图片描述
  • 键值对删除可以使用 UNLINK命令
  • 清空数据库在FLUSHDB和FLUSHALL 加上ASYNC选项,子线程异步删除
  1. lazy-free是4.0新增的功能,但是默认是关闭的,需要手动开启。
  2. 手动开启lazy-free时,有4个选项可以控制,分别对应不同场景下,要不要开启异步释放内存机制:
    a) lazyfree-lazy-expire:key在过期删除时尝试异步释放内存
    b) lazyfree-lazy-eviction:内存达到maxmemory并设置了淘汰策略时尝试异步释放内存
    c) lazyfree-lazy-server-del:执行RENAME/MOVE等命令或需要覆盖一个key时,删除旧key尝
    试异步释放内存
    精选留言 (45)
    d) replica-lazy-flush:主从全量同步,从库清空数据库时异步释放内存
  3. 即使开启了lazy-free,如果直接使用DEL命令还是会同步删除key,只有使用UNLINK命令
    才会可能异步删除key。
  4. 除了replica-lazy-flush之外,其他情况都只是可能去异步释放key的内存,并不是每次必定异步释放内存的。
    • 开启lazy-free后,Redis在释放一个key的内存时,首先会评估代价,如果释放内存的代价很
      小,那么就直接在主线程中操作了,没必要放到异步线程中执行(和key的类型、编码方式、元素数量都有关系)
    • a) 当Hash/Set底层采用哈希表存储(非ziplist/int编码存储)时,并且元素数量超过64个
      b) 当ZSet底层采用跳表存储(非ziplist编码存储)时,并且元素数量超过64个
      c) 当List链表节点数量超过64个(注意,不是元素数量,而是链表节点的数量,List的实现是
      在每个节点包含了若干个元素的数据,这些元素采用ziplist存储)
    • String(不管内存占用多大)、List(少量元素)、Set(int编码存储)、Hash/ZSet(ziplist编码存储)这些情况下的key在释放内存时,依旧在主线程中操作。

CPU对redis的影响

单 CPU
在这里插入图片描述

多 CPU Socket 架构
在这里插入图片描述

非统一内存访问架构(Non-Uniform Memory Access,NUMA 架构):在多 CPU 架构下,一个应用程序访问所在 Socket 的本地内存和访问远端内存的延迟并不一致。

  • 将redis实例绑定一个CPU核,可以减少redis在不同核的切换
  • taskset -c 0 ./redis-server 将redis实例绑定在0号核上。

在这里插入图片描述

  • 为了提升 Redis 的网络性能,把操作系统的网络中断处理程序和 CPU 核绑定。这个做法可以避免网络中断处理程序在不同核上来回调度执行,的确能有效提升 Redis 的网络处理性能。
  • 如果网络中断处理程序和 Redis 实例各自所绑的 CPU 核不在同一个CPU Socket 上,那么,Redis 实例读取网络数据时,就需要跨 CPU Socket 访问内存,这个过程会花费较多时间。
  • 在 CPU 的 NUMA 架构下,对 CPU 核的编号规则,并不是先把一个CPU Socket 中的所有逻辑核编完,再对下一个 CPU Socket 中的逻辑核编码,而是先给每个 CPU Socket 中每个物理核的第一个逻辑核依次编号,再给每个 CPU Socket 中的物理核的第二个逻辑核依次编号。

绑核的风险和解决方案

  • 当我们把 Redis 实例绑到一个 CPU 逻辑核上时,就会导致子进程、后台线程和 Redis 主线程
    竞争 CPU 资源,一旦子进程或后台线程占用 CPU 时,主线程就会被阻塞,导致 Redis 请求
    延迟增加。
    • 一个 Redis 实例对应绑一个物理核
    • 优化 Redis 源码(把子进程和后台线程绑到不同的 CPU 核上)
      +
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值