哈喽大家好,我是阿Q!
前两天去美团面试的陈同学回来了,看他满脸泄气的样子,准是没拿到 Offer。
听了他面试的经过,真替他感到惋惜。究其原因,是被一道面试题拦住了去路:看你简历上写着精通 Redis,请你总结一下 Redis 中存在的阻塞问题吧。
正好阿Q这几天正在研究 Redis,就顺便在这儿给大家做个总结。
命令阻塞
使用不当的命令造成客户端阻塞:
这些命令时间复杂度是O(n),有时候也会全表扫描,随着n的增大耗时也会越大从而导致客户端阻塞。
SAVE 阻塞
大家都知道 Redis 在进行 RDB 快照的时候,会调用系统函数 fork() ,创建一个子线程来完成临时文件的写入,而触发条件正是配置文件中的 save 配置。
当达到我们的配置时,就会触发 bgsave 命令创建快照,这种方式是不会阻塞主线程的,而手动执行 save 命令会在主线程中执行,阻塞主线程。
同步持久化
当 Redis 直接记录 AOF 日志时,如果有大量的写操作,并且配置为同步持久化
即每次发生数据变更会被立即记录到磁盘,因为写磁盘比较耗时,性能较差,所以有时会阻塞主线程。
BGREWRITEAOF
命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子线程创建新 AOF 文件期间,记录服务器执行的所有写命令。阻塞就是出现在第2步的过程中,将缓冲区中新数据写到新文件的过程中会产生阻塞。
AOF 的日志记录不像关系型数据库那样在执行命令之前记录日志(方便故障恢复),而是采用先执行命令后记录日志的方式。
原因就是 AOF 记录日志是不会对命令进行语法检查的,这样就能减少额外的检查开销,不会对当前命令的执行产生阻塞,但可能会给下一个操作带来阻塞风险。
这是因为 AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了。
大 key 并不是指 key 的值很大,而是 key 对应的 value 很大。
大 key 造成的阻塞问题如下:
查找大 key
当我们在使用 Redis 自带的 --bigkeys
参数查找大 key 时,最好选择在从节点上执行该命令,因为主节点上执行时,会阻塞主节点。
删除操作的本质是要释放键值对占用的内存空间。
释放内存只是第一步,为了更加高效地管理内存空间,在应用程序释放内存时,操作系统需要把释放掉的内存块插入一个空闲内存块的链表,以便后续进行管理和再分配。这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序。
责任编辑:木真 来源:阿Q说代码