Redis的异步机制是什么
一、Redis 的阻塞点
和 Redis 实例交互的对象,以及交互时会发生的操作:
客户端:网络 IO,键值对增删改查操作,数据库操作;
磁盘:生成 RDB 快照,记录 AOF 日志,AOF 日志重写;
主从节点:主库生成、传输 RDB 文件,从库接收 RDB 文件、清空数据库、加载 RDB 文件;
切片集群实例:向其他实例传输哈希槽信息,数据迁移。
4 类交互对象和具体的操作之间的关系:
和客户端交互时的阻塞点:
网络 IO 有时候会比较慢,但是 Redis 使用了 IO 多路复用机制,避免了主线程一直处在等待网络连接或请求到来的状态,所以网络 IO 不是导致 Redis 阻塞的因素。
Redis 主线程的主要任务是执行与客户端交互的键值对的增删改查操作。复杂度高的增删改查操作肯定会阻塞 Redis。
判断操作复杂度高低的标准:看操作的复杂度是否为 O(N)。
Redis 的第一个阻塞点:集合全量查询和聚合操作:
Redis 中涉及集合的操作复杂度通常为 O(N),使用时需重视起来。
例如集合元素全量查询操作 HGETALL、SMEMBERS,以及集合的聚合统计操作,例如求交、并和差集。
Redis 的第二个阻塞点 :bigkey 删除操作
集合自身的删除操作同样也有潜在的阻塞风险。删除操作的本质是要释放键值对占用的内存空间。 释放内存只是第一步,为了更加高效地管理内存空间,在应用程序释放内存时,操作系统需要把释放掉的内存块插入一个空闲内存块的链表,以便后续进行管理和再分配。
这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序,如果一下子释放了大量内存,空闲内存块链表操作时间就会增加,相应地就会造成 Redis 主线程的阻塞。
释放大量内存的时机:在删除大量键值对数据的时候,删除包含了大量元素的集合,也称为 bigkey 删除。
不同元素数量的集合在进行删除操作时所消耗的时间:
得出三个结论:
当元素数量从 10 万增加到 100 万时,4 大集合类型的删除时间的增长幅度从 5 倍上升到了近 20 倍;
集合元素越大,删除所花费的时间就越长;
删除一个包含100万个元素的集合时,Hash类型的最大删除时间已经达到了1.98秒的绝对值。一般情况下,Redis 响应时间在微秒级别,但如果某个操作需要近2秒的执行时间,则会阻塞主线程,这是无法避免的。
Redis 的第三个阻塞点:清空数据库
既然频繁删除键值对都是潜在的阻塞点了,在 Redis 的数据库级别操作中,清空数据库(例如 FLUSHDB 和 FLUSHALL 操作)也是一个潜在的阻塞风险,因为它涉及到删除和释放所有的键值对。
Redis 的第四个阻塞点:AOF 日志同步写
磁盘 IO 一般都是比较费时费力的,需要重点关注。 Redis 开发者早已认识到磁盘 IO 会带来阻塞,所以把 Redis 设计为采用子进程的方式生成 RDB 快照文件、执行 AOF 日志重写操作。由子进程负责执行,慢速的磁盘 IO 就不会阻塞主线程了。
如果 Redis 直接记录 AOF 日志,它会利用不同的写入策略将数据写入磁盘。一个同步写磁盘的操作的耗时大约是 1~2ms,如果有大量的写操作需要记录在 AOF 日志中,并同步写回的话,会阻塞主线程。
Redis 的第五个阻塞点:从库加载 RDB 文件
在主从集群中,主库需要生成 RDB 文件,并传输给从库。
主库在复制的过程中,创建和传输 RDB 文件都是由子进程来完成的,不会阻塞主线程。
但是从库在接收了 RDB 文件后,需要使用 FLUSHDB 命令清空当前数据库,正好撞上了第三个阻塞点。
从库在清空当前数据库后,需要把 RDB 文件加载到内存,这个过程的快慢和 RDB 文件的大小密切相关,RDB 文件越大,加载过程越慢。
切片集群实例交互时的阻塞点
部署 Redis 切片集群时,每个 Redis 实例上分配的哈希槽信息需要在不同实例间进行传递,当需要进行负载均衡或者有实例增删时,数据会在不同的实例间进行迁移。不过哈希槽的信息量不大,而数据迁移是渐进式执行的,这两类操作对 Redis 主线程的阻塞风险不大。
如果使用了 Redis Cluster 方案,而且同时正好迁移的是 bigkey 的话,就会造成主线程的阻塞,因为 Redis Cluster 使用了同步迁移。
五个阻塞点:
集合全量查询和聚合操作;
bigkey 删除;
清空数据库;
AOF 日志同步写;
从库加载 RDB 文件。
二、可以异步执行的阻塞点
为了避免阻塞式操作,Redis 提供了异步线程机制:
Redis 会启动一些子线程,然后把一些任务交给这些子线程,让它们在后台完成,而不再由主线程来执行这些任务。可以避免阻塞主线程。
异步执行对操作的要求:
一个能被异步执行的操作并不是 Redis 主线程的关键路径上的操作(客户端把请求发送给 Redis 后,等着 Redis 返回数据结果的操作)。
主线程接收到操作 1 后,操作 1 并不用给客户端返回具体的数据,主线程可以把它交给后台子线程来完成,同时只要给客户端返回一个“OK”结果就行。
在子线程执行操作 1 的时候,客户端又向 Redis 实例发送了操作 2,客户端是需要使用操作 2 返回的数据结果的,如果操作 2 不返回结果,那么客户端将一直处于等待状态。
操作 1 就不算关键路径上的操作,因为它不用给客户端返回具体数据,所以可以由后台子线程异步执行。
操作 2 需要把结果返回给客户端,它就是关键路径上的操作,所以主线程必须立即把这个操作执行完。
Redis 读操作是典型的关键路径操作,因为客户端发送了读操作之后,就会等待读取的数据返回,以便进行后续的数据处理。而 Redis 的第一个阻塞点“集合全量查询 和聚合操作”都涉及到了读操作,不能进行异步操作。
不需要将具体的数据结果返回给客户端的删除操作不属于关键路径操作。"Both 'bigkey deletion' and 'database clearance' involve deleting data, but they are not on the critical path."。可以使用后台子线程来异步执行删除操作。
“AOF 日志同步写”,为了保证数据可靠性,Redis 实例需要保证 AOF 日志中的操作记录已经落盘,这个操作虽然需要实例等待,但它并不会返回具体的数据结果给实例。所以可以启动一个子线程来执行 AOF 日志的同步写。
为了向客户端提供数据存取服务,必须加载完整的 RDB 文件。这个操作也属于关键路径上的操作,必须让从库的主线程来执行。
除了“集合全量查询和聚合操作”和“从库加载 RDB 文 件”,其他三个阻塞点涉及的操作都不在关键路径上,可以使用 Redis 的异步子线程机制来实现 bigkey 删除,清空数据库,以及 AOF 日志同步写。
三、异步的子线程机制
Redis 主线程启动后,会使用操作系统提供的 pthread_create 函数创建 3 个子线程,负责AOF 日志写操作、键值对删除、文件关闭的异步执行。
主线程通过一个链表形式的任务队列和子线程进行交互。
当收到键值对删除和清空数据库的操作时,主线程会把这个操作封装成一个任务,放入到任务队列中,然后给客户端返回一个完成信息,表明删除已经完成。
但实际上,这个时候删除还没有执行,等到后台子线程从任务队列中读取任务后,才开始实际删除键值对,并释放相应的内存空间。这种异步删除也称为惰性删除 (lazy free)。
当 AOF 日志配置成 everysec 选项后,主线程会把 AOF 写日志操作封装成一个任务,也放到任务队列中。一种重写方式是: 当后台子线程读取到任务后,即开始自行记录到AOF日志,主线程即可脱离对AOF日志的依赖而继续运行。
Redis 中的异步子线程执行机制:
异步的键值对删除和数据库清空操作是 Redis 4.0 后提供的功能,Redis 也提供了新的命令来执行这两个操作:
键值对删除:集合类型中有大量元素(例如有百万级别或千万级别元素)需要删除时,建议使用 UNLINK 命令;
清空数据库:可以在 FLUSHDB 和 FLUSHALL 命令后加上 ASYNC 选项,让后台子线程异步地清空数据库。
FLUSHDB ASYNC FLUSHALL AYSNC
以上是Redis的异步机制是什么的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Redis集群模式通过分片将Redis实例部署到多个服务器,提高可扩展性和可用性。搭建步骤如下:创建奇数个Redis实例,端口不同;创建3个sentinel实例,监控Redis实例并进行故障转移;配置sentinel配置文件,添加监控Redis实例信息和故障转移设置;配置Redis实例配置文件,启用集群模式并指定集群信息文件路径;创建nodes.conf文件,包含各Redis实例的信息;启动集群,执行create命令创建集群并指定副本数量;登录集群执行CLUSTER INFO命令验证集群状态;使

如何清空 Redis 数据:使用 FLUSHALL 命令清除所有键值。使用 FLUSHDB 命令清除当前选定数据库的键值。使用 SELECT 切换数据库,再使用 FLUSHDB 清除多个数据库。使用 DEL 命令删除特定键。使用 redis-cli 工具清空数据。

要从 Redis 读取队列,需要获取队列名称、使用 LPOP 命令读取元素,并处理空队列。具体步骤如下:获取队列名称:以 "queue:" 前缀命名,如 "queue:my-queue"。使用 LPOP 命令:从队列头部弹出元素并返回其值,如 LPOP queue:my-queue。处理空队列:如果队列为空,LPOP 返回 nil,可先检查队列是否存在再读取元素。

使用 Redis 指令需要以下步骤:打开 Redis 客户端。输入指令(动词 键 值)。提供所需参数(因指令而异)。按 Enter 执行指令。Redis 返回响应,指示操作结果(通常为 OK 或 -ERR)。

使用Redis进行锁操作需要通过SETNX命令获取锁,然后使用EXPIRE命令设置过期时间。具体步骤为:(1) 使用SETNX命令尝试设置一个键值对;(2) 使用EXPIRE命令为锁设置过期时间;(3) 当不再需要锁时,使用DEL命令删除该锁。

在CentOS系统上,您可以通过修改Redis配置文件或使用Redis命令来限制Lua脚本的执行时间,从而防止恶意脚本占用过多资源。方法一:修改Redis配置文件定位Redis配置文件:Redis配置文件通常位于/etc/redis/redis.conf。编辑配置文件:使用文本编辑器(例如vi或nano)打开配置文件:sudovi/etc/redis/redis.conf设置Lua脚本执行时间限制:在配置文件中添加或修改以下行,设置Lua脚本的最大执行时间(单位:毫秒)

使用 Redis 命令行工具 (redis-cli) 可通过以下步骤管理和操作 Redis:连接到服务器,指定地址和端口。使用命令名称和参数向服务器发送命令。使用 HELP 命令查看特定命令的帮助信息。使用 QUIT 命令退出命令行工具。

在Debian系统中,readdir系统调用用于读取目录内容。如果其性能表现不佳,可尝试以下优化策略:精简目录文件数量:尽可能将大型目录拆分成多个小型目录,降低每次readdir调用处理的项目数量。启用目录内容缓存:构建缓存机制,定期或在目录内容变更时更新缓存,减少对readdir的频繁调用。内存缓存(如Memcached或Redis)或本地缓存(如文件或数据库)均可考虑。采用高效数据结构:如果自行实现目录遍历,选择更高效的数据结构(例如哈希表而非线性搜索)存储和访问目录信
