Redis 内部的阻塞式操作以及应对的方法。

主线程阻塞

如果在主线程上执行的操作消耗的时间太长,就会引起主线程阻塞。但是,Redis 既有服务客户端请求的键值对增删改查操作,也有保证可靠性的持久化操作,还有进行主从复制时的数据同步操作,等等。操作这么多,究竟哪些会引起阻塞

Redis 实例有哪些阻塞点

  • 客户端:网络 IO,键值对增删改查操作,数据库操作
  • 磁盘:生成 RDB 快照,记录 AOF 日志,AOF 日志重写;
  • 主从节点:主库生成、传输 RDB 文件,从库接收 RDB 文件、清空数据库、加载 RDB 文件;
  • 切片集群实例:向其他实例传输哈希槽信息,数据迁移。

和客户端交互时的阻塞点

  • 集合全量查询和聚合操作。
    Redis 中涉及集合的操作复杂度通常为 O(N),复杂度高的增删改查操作肯定会阻塞 Redis,例如集合元素全量查询操作 HGETALL、SMEMBERS,以及集合的聚合统计操作,例如求交、并和差集。
  • bigkey 删除操作
    删除操作的本质是要释放键值对占用的内存空间,释放内存只是第一步,为了更加高效地管理内存空间,在应用程序释放内存时,操作系统需要把释放掉的内存块插入一个空闲内存块的链表,以便后续进行管理和再分配。这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序,所以,如果一下子释放了大量内存,空闲内存块链表操作时间就会增加,相应地就会造成 Redis 主线程的阻塞。
集合类型10W (8byte)100W(8byte)10W (128byte)100W(128byte)
hash50ms962ms91ms1980ms
List25ms133ms29ms283ms
set42ms821ms75ms1347ms
zset53ms809ms61ms991ms

当元素数量从 10 万增加到 100 万时,4 大集合类型的删除时间的增长幅度从 5 倍上升到了近 20 倍;

集合元素越大,删除所花费的时间就越长;

当删除有 100 万个元素的集合时,最大的删除时间绝对值已经达到了 1.98s(Hash 类型)。Redis 的响应时间一般在微秒级别,所以,一个操作达到了近 2s,不可避免地会阻塞主线程。

  • 清空数据库

和磁盘交互时的阻塞点

Redis 进一步设计为采用子进程的方式生成 RDB 快照文件,以及执行 AOF 日志重写操作。这样一来,这两个操作由子进程负责执行,慢速的磁盘 IO 就不会阻塞主线程了。
但是Redis 直接记录 AOF 日志时,会根据不同的写回策略对数据做落盘保存。一个同步写磁盘的操作的耗时大约是 1~2ms,如果有大量的写操作需要记录在 AOF 日志中,并同步写回的话,就会阻塞主线程了

主从节点交互时的阻塞点

主从集群中,主库需要生成 RDB 文件,并传输给从库。主库在复制的过程中,创建和传输 RDB 文件都是由子进程来完成的,不会阻塞主线程。但是,对于从库来说,它在接收了 RDB 文件后,需要使用 FLUSHDB 命令清空当前数据库

集群实例交互时的阻塞点

使用了 Redis Cluster 方案,而且同时正好迁移的是 bigkey 的话,就会造成主线程的阻塞

bigkey 删除、清空数据库、AOF 日志同步写不属于关键路径操作,可以使用异步子线程机制来完成。Redis 在运行时会创建三个子线程,主线程会通过一个任务队列和三个子线程进行交互。子线程会根据任务的具体类型,来执行相应的异步操作。
异步删除操作是 Redis 4.0 以后才有的功能,如果你使用的是 4.0 之前的版本,当你遇到 bigkey 删除时,可以先使用集合类型提供的 SCAN 命令读取数据,然后再进行删除。因为用 SCAN 命令可以每次只读取一部分数据并进行删除,这样可以避免一次性删除大量 key 给主线程带来的阻塞。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RedisTemplate是Spring Data Redis提供的一个用于操作Redis的模板类。它封装了对Redis的常见操作,提供了一系列的方法来简化对Redis的访问。 RedisTemplate的作用主要有以下几个方面: 1. 提供了对Redis的常见操作的封装,包括字符串、哈希、列表、集合、有序集合等数据结构的操作。 2. 提供了对Redis事务的支持,可以通过RedisTemplate实现对多个Redis命令的原子性执行。 3. 提供了对Redis的连接管理,包括连接池的管理和连接的获取与释放。 RedisTemplate的常用方法包括: 1. 字符串操作: - set(key, value):设置指定key的值为value。 - get(key):获取指定key的值。 - delete(key):删除指定key。 2. 哈希操作: - hset(key, field, value):设置指定key的哈希表中指定field的值为value。 - hget(key, field):获取指定key的哈希表中指定field的值。 - hdel(key, field):删除指定key的哈希表中指定field。 3. 列表操作: - lpush(key, value):将value插入到指定key的列表的头部。 - rpop(key):移除并返回指定key的列表的尾部元素。 - lrange(key, start, end):获取指定key的列表中指定范围内的元素。 4. 集合操作: - sadd(key, value):将value添加到指定key的集合中。 - smembers(key):获取指定key的集合中的所有成员。 - zadd(key, score, value):将value添加到指定key的有序集合中,并设置其分数为score。 - zrange(key, start, end):获取指定key的有序集合中指定范围内的成员。 - zrem(key, value):从指定key的有序集合中移除value。 这些只是RedisTemplate提供的一部分常用方法,还有其他更多的方法可以根据具体需求进行使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值