这次,我们将说一下,Redis中可能出现的阻塞情况,以及Redis后续进行的优化

Redis在实例运行的过程中,要和很多的对象进行交互,那么其阻塞的发生点,应该就在其中

对于客户端,存在着网络IO交互,以及键值对增删改查的操作

磁盘则存在RDB快照和AOF日志记录及重写

主从节点则存在着主库生成,传输RDB文件,从库接收RDB文件,加载RDB文件

切片集群中的哈希槽重分配,数据传输

图片

1.我们先说和客户端交互的部分,对于网络IO,一般来说不必担心,因为Redis使用了IO多路复用,不会出现阻塞在网络上的状态

其次是键值对的增删改查,这一部分是大头,也是会阻塞Redis的主要原因,复杂度高的增删改查一定会阻塞Redis,在操作过程中,复杂度为O(N)的,都存在阻塞主线程的风险,比如集合元素全量查询HGETALL SMEMBERS,集合的聚合操作,求交集并集/差集,这就是第一个阻塞点

还有就是集合的删除操作也有阻塞的风险,因为删除操作需要释放其占用的内存空间,如果释放的内存过大,也会造成Redis主线程的阻塞

因为大量内存释放会导致阻塞,故释放大量键值对数据的时候,被称为bigkey删除

同理可以推断,再删除和清空数据库的时候,也会导致Redis的阻塞

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

因为磁盘IO的缓慢,所以诞生了Redis,而Redis的持久化还需要磁盘IO,所以Reids记录AOF日志,可能也会因为磁盘IO阻塞主线程,这也就是Redis的第四个阻塞点了:AOF日志同步写

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

在主从库交互的时候,主库发送RDB文件是由子线程做的,所以不必担心阻塞,而从库接收了RDB,需要清库后重新加载RDB文件,这也是个阻塞点

4.切片集群的重分配

当切片集群中,需要哈希槽重分配以及数据迁移的时候,如果是使用了Redis Cluster这样的同步迁移的时候,在面对bigkey的迁移的时候,就会阻塞主线程

那么,总结一下上面的阻塞点

全量查询和聚合操作

bigkey的删除

清空数据库

AOF日志的同步写

从库加载RDB文件

切片集群的重分配

上面的阻塞式操作,那些可以被异步执行从而解决呢?

那就需要明确,哪些操作是可以被统计的了,当一个客户端发给Redis,需要Redis立刻执行并返回结果的操作,就是关键路径上的操作,反之则不是,不是的操作可以异步执行

对应到Redis上,读操作就是一个关键路径操作,所以第一个阻塞点 集合全量查询和聚合操作,就涉及了读操作,就不能进行异步操作了

但是对于删除操作,不需要给客户端返回具体数据,可以考虑使用异步来进行加速操作

然后就是AOF日志同步写,为了保证数据的可靠性,需要保证AOF日志中的操作记录以及落盘,但是不需要返回消息给客户端,所以也可以考虑启动子线程来执行AOF的同步写

之后的从库加载RDB文件,如果没有加载完成,也是无法提供给客户端数据存取服务的,所以需要将RDB文件执行到完成,也需要从库的主线程执行

以及最后的切片集群,如果是同步执行重分配,则也无法避免阻塞

说完了可以异步的操作,我们可以说一下异步的子线程机制

Redis会使用操作系统提供的pthread_create 函数创建3个子线程,分别由其负责AOF日志写操作,键值对删除以及文件关闭的异步执行

如果是异步的删除,那么主线程收到删除的请求的时候,会将其封装为一个任务,放入任务队列中,然后给客户端返回一个完成,表明删除完成

然后是AOF日志的同步写,也是将AOF的写日志操作,封装为任务,放入任务队列,让子线程负责写入AOF日志

对应的异步删除,是Redis4.0提供的,Redis也提供了部分异步操作的功能

比如键值对删除的时候,推荐使用UNLINK命令

清空数据库,可以考虑在FLUSHDB或FLUSHALL之后加上ASYNC选项,让后台子线程异步清空数据库

FLUSHDB ASYNC

FLUSHALL AYSNC

那么总结一下本节课,我们学习了Redis实例运行的几个交互对象,包含客户端 磁盘 主从库实例 切片集群实例,以及梳理了可能造成Redis阻塞的几个阻塞点,包含全量查询集合及聚合,bigkey删除,清空数据库,AOF日志同步写,从库加载RDB文件

然后根据是不是需要和客户端交互,分为了关键路径操作和非关键路径操作,对于非关键性操作,可以使用异步子线程机制来完成,Redis在运行的时候会创建三个子线程,主线程会通过一个任务队列和三个子线程进行交互,子线程根据具体的任务类型,执行相对应的异步操作

最后一个小问题,Redis的写操作是在关键路径上吗?

我认为在,因为Reids的写操作可能后续跟着读请求,直接放入异步子线程的话,可能会出现子线程没有及时处理,导致读取的数据不符的问题,所以应该是关键路径上的

发表评论

邮箱地址不会被公开。 必填项已用*标注