异步编程规避Redis的阻塞(下)

Posted JavaEdge.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步编程规避Redis的阻塞(下)相关的知识,希望对你有一定的参考价值。

3 可异步执行的阻塞点

在分析阻塞式操作的异步执行的可行性前,先了解异步执行对操作的要求。

若一个操作能被异步执行,说明它不是Redis主线程关键路径上的操作。

3.1 关键路径操作

客户端把请求发给Redis后,等Redis返回数据结果:

  • 主线程接收到操作1后,由于操作1无需给客户端返回具体数据,所以,主线程可将其移交给后台子线程处理,同时只需给客户端返回“OK”。
    操作1就不属关键路径操作,因其不用给客户端返回具体数据,所以可由后台子线程异步执行
  • 子线程执行操作1时,客户端又向Redis实例发送操作2,而此时,客户端需使用操作2返回的具体数据结果。若操作2不返回结果,则客户端将一直处等待状态。
    该操作需把结果返给客户端,所以是关键路径操作,主线程须立即执行完该操作。

那Redis的写操作(如SET,HSET,SADD)属于关键路径吗?这需要客户端根据业务需要区分:

  • 若客户端依赖操作返回值的不同而处理不同业务逻辑,则HSET、SADD算关键路径,而SET操作不算关键路径

    因为HSET和SADD操作,若field或member不存在,Redis返回1,否则返0。而SET操作返回的结果都是OK

  • 若客户端不关心返回值,只关心数据是否写成功,则SET/HSET/SADD都不算关键路径,多次执行这些命令都是幂等的,这时可放到异步线程

  • 若Redis设置maxmemory,但未设置淘汰策略,这三个操作也都算关键路径

    因为若Redis内存超过maxmemory,再写入数据时,Redis返回的结果是OOM error,这种情况下,客户端需要感知有错误发生才行

3.2 各阻塞点分析

3.2.1 集合全量查询和聚合操作

Redis读肯定都是关键路径操作,因为客户端发起读请求后,就会等待返回读取数据,再处理后续。
所以,都涉及读操作,无法异步!

推荐使用SCAN命令,分批读取数据,再在客户端进行聚合计算;

3.2.2 删除操作

无需给客户端返回具体数据,所以不算关键路径操作。“大K删除”、“清空数据库”同理,都可用后台子线程异步执行。

3.2.3 AOF日志同步写

为保证数据可靠性,Redis实例需保证AOF日志中的操作记录已落盘,这个操作虽需实例等待,但并不会返回具体数据结果给实例。所以,也可使用一个子线程执行AOF日志同步写。

3.2.4 从库加载RDB文件

从库想对客户端提供数据存取服务,须将RDB文件加载完成。所以,这也属于关键路径操作,必须让从库主线程执行。把主库的数据量大小控制在2~4GB左右,以保证RDB文件能以较快的速度加载。

综上,可使用Redis异步子线程机制实现大K删除,清空数据库及AOF日志同步写。

以上是关于异步编程规避Redis的阻塞(下)的主要内容,如果未能解决你的问题,请参考以下文章

异步编程规避Redis的阻塞(上)

异步编程规避Redis的阻塞(中)

异步编程规避Redis的阻塞(中)

BIONIO 和 AIO 有什么区别?

网络编程NIO-异步

深入剖析 Spring WebFlux