Redis深度解析:场景、锁、队列、Big Key与缓存优化

引言

  • 简要介绍Redis
  • Redis的优势和适用场景

一、Redis使用场景

  • 缓存系统:缓存热点数据,减轻数据库压力,提高应用响应速度。
  • 会话存储:替代传统的服务器端会话存储,减轻服务器负载,实现会话数据的快速存取。
  • 计数器:实现快速自增自减操作,常用于限流、统计等场景。
  • 排行榜/排序:基于Redis的有序集合(Sorted Set)实现实时更新的排行榜功能。
  • 分布式锁:实现跨多个服务或实例的同步控制,确保同一时间只有一个客户端能够访问共享资源。
  • 消息队列:Redis可以实现轻量级的消息系统,用于解耦系统、异步处理任务等。

二、Redis实现分布式锁

  • Redis分布式锁原理
  • 使用SETNX、EXPIRE等命令实现分布式锁
  • Java示例代码(使用Jedis或Lettuce库)
// 伪代码片段  
public synchronized boolean tryLock(String lockKey, String requestId, int expireTime) {  // 使用SETNX命令尝试获取锁  // ...  return true; // 或false  
}  public synchronized void unlock(String lockKey, String requestId) {  // 释放锁的逻辑  // ...  
}

Redis实现分布式锁的原理主要基于Redis的多个实例之间的协作,以确保在分布式系统中多个节点对共享资源的互斥访问。以下是Redis实现分布式锁的详细原理:

一、基本思想

Redis分布式锁通过Redis的SETNX(SET IF NOT EXISTS)命令或SET命令结合多个参数(如NX、PX等)来实现。这些命令允许在键不存在时设置键的值,或者在设置键的值的同时设置键的过期时间。通过这种方式,Redis可以作为一个中央化的锁管理器,协调多个节点对共享资源的访问。

二、实现步骤

  1. 加锁:客户端使用SETNX命令尝试获取锁。如果键不存在,则设置键的值(通常为客户端的唯一标识符,如UUID或请求ID)并返回1,表示加锁成功。如果键已存在,则返回0,表示加锁失败。为了避免客户端永远无法获取到锁(如锁被其他客户端持有且未释放),可以设置锁的过期时间。这可以通过SET命令的PX参数来实现,该参数指定了键的过期时间(以毫秒为单位)。
  2. 释放锁:当客户端完成操作后,需要释放锁。这通常通过DEL命令删除键来实现。然而,为了确保只有锁的持有者才能释放锁,客户端在删除键之前需要检查键的值是否与自己的唯一标识符相匹配。这可以通过GET命令和条件删除(如Lua脚本)来实现。
  3. 解决死锁:如果锁的持有者崩溃或删除锁失败,其他客户端将无法获取到锁,导致死锁。为了解决这个问题,可以在获取锁时检查锁的过期时间。如果锁的过期时间小于当前时间,则认为锁已过期,其他客户端可以尝试获取锁。

三、Redis实现消息队列

  • Redis消息队列的设计
  • 使用List或Stream实现消息队列
  • 发布/订阅模式
  • Java示例代码(使用Jedis或Lettuce库)
// 伪代码片段  
jedis.lpush("mylist", "message1"); // 生产消息  
String message = jedis.rpop("mylist"); // 消费消息

Redis 作为一个内存中的数据结构存储系统,它可以用作数据库、缓存和消息中介。由于其高性能和丰富的数据结构,Redis 在实现消息队列方面非常高效。以下我们将探讨如何使用 Redis 的 List(列表)或 Stream(流)来实现消息队列,以及如何使用 Redis 的发布/订阅模式。

使用List实现消息队列

Redis 的 List 是一种双向链表结构,它支持在两端插入和删除元素。这使得 List 非常适合用作消息队列。生产者可以将消息 LPUSH 到列表的一端,而消费者可以 BRPOP 或 BLPOP 从列表的另一端获取并移除消息。

生产者示例(Java 使用 Jedis)

Jedis jedis = new Jedis("localhost");  
String listKey = "myqueue";  
String message = "Hello, Redis Queue!";  
jedis.lpush(listKey, message);

消费者示例(Java 使用 Jedis)

Jedis jedis = new Jedis("localhost");  
String listKey = "myqueue";  
List<String> messages = jedis.brpop(0, listKey); // 等待时间为0表示阻塞直到有消息  
String message = messages.get(1); // 索引1是消息内容,索引0是队列名  
System.out.println(message); // 输出消息内容

使用Stream实现消息队列(Redis 5.0+)

Redis Stream 是 Redis 5.0 引入的一个新特性,它提供了一个可持久化的、只追加的消息队列。与 List 相比,Stream 提供了更多的消费者组(Consumer Group)和消息确认(Message Acknowledgment)机制,使得它更适合复杂的消息处理场景。

生产者示例(Java 使用 Jedis 或 Lettuce)

在 Redis Stream 中,生产者使用 XADD 命令添加消息。

// Jedis 或 Lettuce 的 Stream API 可能会有所不同,这里仅提供伪代码  
String streamName = "mystream";  
Map<String, String> messageBody = new HashMap<>();  
messageBody.put("field1", "value1");  
String messageId = jedis.xadd(streamName, null, messageBody); // 第一个参数是流名,第二个参数是消息ID(可以为null以自动生成),第三个参数是消息内容

消费者示例(Java 使用 Jedis 或 Lettuce)

消费者使用 XREADGROUP 命令从 Stream 中读取消息,并使用 XACK 命令确认消息已被处理。

// 伪代码  
String groupName = "mygroup";  
String consumerName = "myconsumer";  
String startId = "$"; // 从最新消息开始读取  
List<Entry<String, List<Map<String, String>>>> pendingMessages = jedis.xreadgroup(groupName, consumerName, Collections.singletonList(new Entry<>(streamName, startId)));  
// 处理消息...  
// 确认消息已处理  
jedis.xack(streamName, groupName, messageId); // messageId 是需要确认的消息的ID

发布/订阅模式

除了使用 List 或 Stream 来实现点对点的消息队列外,Redis 还提供了发布/订阅模式(Pub/Sub),它允许客户端订阅一个或多个频道(Channel),并接收发送到这些频道的消息。发布/订阅模式通常用于实现广播式的消息传递。

发布者示例(Java 使用 Jedis)

Jedis jedis = new Jedis("localhost");  
String channel = "mychannel";  
String message = "Hello, Redis Subscribers!";  
jedis.publish(channel, message);

订阅者示例(Java 使用 Jedis)

订阅者使用 PSUBSCRIBE 或 SUBSCRIBE 命令订阅频道,并使用 onPMessage 或 onMessage 回调函数来处理接收到的消息。

JedisPubSub jedisPubSub = new JedisPubSub() {  @Override  public void onPMessage(String pattern, String channel, String message) {  System.out.println("Received message on channel " + channel + ": " + message);  }  
};  
Jedis jedis = new Jedis("localhost");  
jedis.psubscribe(jedisPubSub, "my*"); // 订阅所有以 "my" 开头的频道  
// 注意:由于订阅是阻塞的,通常在一个单独的线程中执行

四、Redis解决Big Key的问题

  • Big Key的定义和影响
  • 识别Big Key
  • 拆分Big Key
  • 使用Hash数据结构
  • Java示例代码(拆分和查询Hash)
// 伪代码片段  
jedis.hset("bigkeyhash", "field1", "value1"); // 使用Hash存储数据  
Map<String, String> result = jedis.hgetAll("bigkeyhash"); // 获取Hash数据

Redis解决Big Key的问题

Big Key的定义和影响

Big Key 是指 Redis 中存储的键值对(key-value pair)的值部分非常大,比如一个包含成百上千个字段的 Hash 类型,或者一个包含大量元素的 List、Set、Sorted Set 类型。Big Key 会对 Redis 的性能和稳定性产生负面影响:

  1. 内存占用:Big Key 会占用大量的内存空间,可能导致 Redis 内存使用迅速增长,甚至耗尽服务器内存。
  2. 阻塞:在操作 Big Key 时,比如获取(GET)、删除(DEL)、序列化/反序列化等,Redis 会消耗更多的时间处理这些请求,导致其他请求的响应延迟增加,甚至造成阻塞。
  3. 网络传输:当 Big Key 在客户端和 Redis 服务器之间传输时,会占用大量的网络带宽,增加网络延迟。
  4. 备份和恢复:包含 Big Key 的 Redis 数据备份和恢复速度会变慢。
  5. 主从同步:主从复制过程中,Big Key 会导致主节点向从节点发送大量数据,影响同步效率。

识别Big Key

为了识别 Big Key,可以使用以下工具和方法:

  1. redis-cli --bigkeys:Redis 官方提供的 redis-cli 工具支持 --bigkeys 选项,用于扫描 Redis 实例并找出 Big Key。
  2. MEMORY USAGE 命令:Redis 提供了 MEMORY USAGE 命令来估算指定键的内存使用情况。
  3. 第三方工具:如 redis-rdb-tools、redis-memory-analyzer 等,这些工具可以分析 RDB 快照文件或实时分析 Redis 内存使用情况。

拆分Big Key

一旦识别出 Big Key,就需要对其进行拆分以减少其大小。以下是几种拆分 Big Key 的方法:

  1. Hash数据结构:将原来的 Big Key 拆分成多个小的 Hash,每个 Hash 存储一部分数据。例如,原本一个包含 1000 个字段的 Hash 可以拆分成 10 个包含 100 个字段的 Hash。
  2. List、Set、Sorted Set 的分页:对于 List、Set、Sorted Set 类型的 Big Key,可以使用分页的方式来获取和处理数据。例如,每次只获取和处理一部分元素,而不是一次性获取整个集合。
  3. 时间序列数据:如果 Big Key 是时间序列数据(如日志、监控数据等),可以考虑使用 Redis 的 Stream 或其他时间序列数据库来存储和查询数据。

使用Hash数据结构

Hash 是 Redis 中一种常用的数据结构,它允许存储多个字段和对应的值。当需要拆分 Big Key 时,可以使用 Hash 来存储原本 Big Key 中的一部分数据。

例如,原本有一个包含 1000 个用户信息的 Big Key(假设为 bigkey:users),每个用户信息包含多个字段(如 id、name、email 等)。可以将这个 Big Key 拆分成多个小的 Hash,每个 Hash 存储一部分用户信息。具体的拆分方式可以根据实际情况来确定,比如按照用户 ID 的范围或哈希值来拆分。

拆分后的 Hash 可以使用类似 user:123、user:456 这样的键来命名,其中 123、456 是用户 ID。每个 Hash 中存储该用户的所有信息。

在拆分 Big Key 并使用 Hash 数据结构时,需要注意以下几点:

  1. 键名设计:合理设计键名以确保可以唯一地标识每个拆分后的 Hash。
  2. 一致性:确保在拆分和合并过程中数据的一致性。
  3. 原子性:如果需要同时更新多个拆分后的 Hash,需要考虑操作的原子性。可以使用 Lua 脚本来实现原子操作。
  4. 监控和告警:定期监控拆分后的 Hash 的大小,并在必要时进行告警或进一步拆分。

五、Redis的缓存淘汰策略

  • LRU(最近最少使用)
  • LFU(最不经常使用)
  • TTL(过期时间)
  • 配置缓存淘汰策略
  • Java中配置Redis缓存淘汰策略(通常在Redis配置文件中设置)

Redis的缓存淘汰策略

Redis提供了多种缓存淘汰策略,用于在内存达到最大限制时,决定哪些数据应该被移除以释放空间。这些策略对于Redis的性能和缓存效率至关重要。

LRU(最近最少使用)

LRU(Least Recently Used)策略会选择最久未使用的数据进行淘汰。当内存不足以容纳新写入数据时,最少使用的数据最先被淘汰。

LFU(最不经常使用)

LFU(Least Frequently Used)策略是Redis 4.0版本中引入的,它会跟踪数据被访问的频率,并淘汰最不经常使用的数据。LFU策略比LRU更精细,因为它不仅考虑数据被访问的时间,还考虑被访问的次数。

TTL(过期时间)

TTL(Time To Live)并不是一种直接的淘汰策略,但Redis允许为数据设置过期时间。当数据达到其TTL时,它会自动从Redis中删除。这可以作为一种间接的缓存淘汰机制,因为过期的数据将不再占用内存。

配置缓存淘汰策略

在Redis配置文件中(通常是redis.conf),你可以通过maxmemory-policy配置项来设置缓存淘汰策略。以下是一些可能的选项:

  • noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
  • allkeys-lru:使用LRU策略淘汰所有键。
  • allkeys-lfu:使用LFU策略淘汰所有键(需要Redis 4.0或更高版本)。
  • volatile-lru:使用LRU策略淘汰设置了过期时间的键。
  • volatile-lfu:使用LFU策略淘汰设置了过期时间的键(需要Redis 4.0或更高版本)。
  • volatile-ttl:淘汰最接近过期时间的键。
  • volatile-random:随机淘汰设置了过期时间的键。

Java中配置Redis缓存淘汰策略

在Java中,你通常不会直接在代码中配置Redis的缓存淘汰策略。相反,你应该在Redis的配置文件(redis.conf)中进行设置。然后,你的Java应用程序将连接到这个已配置的Redis实例。

然而,如果你使用某种Java客户端(如Jedis、Lettuce或Redisson)和Redis进行交互,并且这些客户端提供了某种形式的配置API,你可能能够检查或报告Redis实例的当前配置(包括缓存淘汰策略),但通常你不能直接通过客户端API更改这些配置。

如果你需要动态更改Redis的配置(包括缓存淘汰策略),你可能需要考虑使用Redis的CONFIG SET命令,但这通常是不推荐的,因为它需要特殊的权限,并且可能会引入风险。在生产环境中,最好是在Redis配置文件中进行静态配置,并在需要时重启Redis服务。

六、Redis的快速读写优化

  • 持久化策略:RDB与AOF
  • 管道(Pipelining)技术
  • 事务(Transactions)
  • Lua脚本
  • 数据结构的选择与优化
  • Redis配置优化(如tcp-backlog、maxmemory等)
  • Java中优化Redis读写(使用连接池、批量操作等)

Redis的快速读写优化

Redis 提供了多种机制和技术来优化其快速读写性能。以下是针对 Redis 性能优化的几个关键方面:

持久化策略:RDB 与 AOF

  • RDB (Redis DataBase):RDB 是 Redis 默认的持久化方式,它会在指定的时间间隔内,将内存中的数据集快照写入磁盘。优点:生成 RDB 文件的速度快,适合用于备份。缺点:数据可能会丢失(因为 RDB 是基于时间间隔的快照)。
  • AOF (Append Only File):AOF 会记录服务器接收到的每一个写操作命令,并在服务器启动时重新执行这些命令来恢复数据。优点:数据持久性更好,几乎不会丢失数据。缺点:AOF 文件比 RDB 文件大,且恢复速度相对较慢。

优化建议

  • 根据业务需求选择适合的持久化策略。
  • 定期检查和优化 AOF 重写和 RDB 快照的频率。

管道(Pipelining)技术

  • 管道技术允许客户端将多个命令打包,一次性发送给服务器,然后等待所有命令的响应。
  • 这减少了网络往返时间(RTT),从而提高了吞吐量。

优化建议

  • 在批量操作或高并发场景下使用管道技术。

事务(Transactions)

  • Redis 提供了简单的事务支持,允许将多个命令打包到一个事务中,确保这些命令的原子性执行。
  • 但请注意,Redis 的事务不支持回滚(除了执行 EXEC 前使用 DISCARD 命令)。

优化建议

  • 在需要确保多个命令原子性执行的场景下使用事务。

Lua 脚本

  • Redis 支持在服务器端执行 Lua 脚本,这允许将多个命令组合到一个脚本中,减少网络往返时间。
  • Lua 脚本在 Redis 服务器内部执行,因此执行速度更快。

优化建议

  • 在需要执行复杂逻辑或需要减少网络往返时间的场景下使用 Lua 脚本。

数据结构的选择与优化

  • Redis 支持多种数据结构,如 String、Hash、List、Set、Sorted Set 等。
  • 选择合适的数据结构对于性能至关重要。

优化建议

  • 根据数据的访问模式和业务需求选择合适的数据结构。
  • 避免使用过于复杂的数据结构,如嵌套的数据结构。

Redis 配置优化

  • Redis 提供了许多配置选项,用于优化其性能。
  • 例如,tcp-backlog、maxmemory、maxmemory-policy、appendfsync 等。

优化建议

  • 根据服务器的硬件和业务需求调整 Redis 配置。
  • 监控 Redis 的性能指标,并根据需要进行调整。

Java 中优化 Redis 读写

  • 使用连接池:连接池可以复用 Redis 连接,减少创建和销毁连接的开销。
  • 批量操作:使用 Redis 的批量操作命令(如 MSET、MGET)或管道技术来减少网络往返时间。
  • 选择合适的序列化方式:使用高效的序列化方式(如 Protocol Buffers、Kryo 等)来减少数据的序列化/反序列化开销。
  • 监控和调优:使用 Redis 监控工具(如 Redis Insight、Redis Commander)来监控 Redis 的性能指标,并根据需要进行调优。

优化建议

  • 在 Java 应用程序中使用 Redis 连接池。
  • 尽可能使用批量操作来减少网络往返时间。
  • 选择合适的序列化方式并监控其性能。
  • 监控 Redis 的性能指标并根据需要进行调优。


项目代码地址:https:
//gitee.com/bseaworkspace/redis-example

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/40017.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WIN32核心编程 - 数据类型 错误处理 字符处理

公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 数据类型 基本数据类型 Win32基本数据类型 错误处理 C语言中的错误处理 C中的错误处理 Win32中的错误处理 字符处理 C/C WIN32 字符处理 数据类型 基本数据类型 C/C语言定义了一系列…

Rocky Linux 9 系统OpenSSH CVE-2024-6387 漏洞修复

Rocky Linux 9系统 OpenSSH CVE-2024-6387 漏洞修复 1、漏洞修复2、修复思路3、修复方案3.1、方案一3.2、方案二 4、总结5、参考 1、漏洞修复 CVE-2024-6387&#xff1a;regreSSHion&#xff1a;OpenSSH 服务器中的远程代码执行&#xff08;RCE&#xff09;&#xff0c;至少在…

【目标检测】DINO

一、引言 论文&#xff1a; DINO: DETR with Improved DeNoising Anchor Boxes for End-to-End Object Detection 作者&#xff1a; IDEA 代码&#xff1a; DINO 注意&#xff1a; 该算法是在Deformable DETR、DAB-DETR、DN-DETR基础上的改进&#xff0c;在学习该算法前&#…

find命令-查找

find命令基本用法 find命令是Linux系统中用于在文件系统中搜索文件和目录的强大工具。它可以根据多种条件来筛选文件,包括文件名、文件类型、文件大小、文件修改时间等。 常见选项和参数 -name <filename>:按照文件名进行搜索。-type <file_type>:按照文件类型进…

《IT 领域准新生暑期预习指南:开启未来科技之旅》

IT专业入门&#xff0c;高考假期预习指南 高考的落幕&#xff0c;只是人生长途中的一个逗号&#xff0c;对于心怀 IT 梦想的少年们&#xff0c;新的征程已然在脚下铺展。这个七月&#xff0c;当分数尘埃落定&#xff0c;你们即将迈向新的知识殿堂&#xff0c;而这个假期&#…

【高考志愿】交通运输工程

目录 一、专业概述 二、课程设置 三、就业前景 四、报考注意 五、未来发展 六、交通运输工程专业排名 高考志愿选择交通运输工程专业&#xff0c;无疑是一个既具远见又富有挑战性的决定。这个专业以其综合性强、实用性高的特点&#xff0c;吸引了大批有志于投身交通事业的…

centos7升级gcc到7.3.0

1、下载gcc-7.3.0源码 wget ftp.gnu.org/gnu/gcc/gcc-7.3.0/gcc-7.3.0.tar.gz 2、解压gcc-7.3.0 tar -xvf gcc-7.3.0.tar.gz3、安装依赖 cd gcc-7.3.0 ./contrib/download_prerequisites ./contrib/download_prerequisites会下载对应的依赖包&#xff0c;如果下载不了的话&a…

【微代码】Linux异步执行机制work基本用法?

文章目录 背景基本代码和用法其他 背景 Linux内核提供诸多异步执行机制&#xff0c;work就是其中一种。work的提供避免了启动多个内核线程造成资源占用等问题。内核提供一个专门的work来进行处理。本文主要记录work的基本用法 基本代码和用法 #include "linux/workqueu…

Day51

JSR-303 简介 JSR全称为 Java Specification Requests&#xff0c;表示 Java 规范提案。JSR-303是 Java 为 Java Bean 数据合法性校验提供的标准框架&#xff0c;它定义了一套可标注在成员变量&#xff0c;属性方法上的校验注解。Hibernate Validatior提供了这套标准的实现。 …

Git使用[推送大于100M的文件后解救办法]

推送大于100M的文件后解救办法 本文摘录于&#xff1a;https://blog.csdn.net/u012150602/article/details/122687435只是做学习备份之用&#xff0c;绝无抄袭之意&#xff0c;有疑惑请联系本人&#xff01; 当有文件大于100M的时候在提交的时候没有问题,但是在push的似乎就不行…

番外篇 | 手把手教你如何去更换YOLOv5的检测头为ASFF_Detect

前言:Hello大家好,我是小哥谈。自适应空间特征融合(ASFF)的主要原理旨在解决单次检测器中不同尺度特征的不一致性问题。具体来说,ASFF通过动态调整来自不同尺度特征金字塔层的特征贡献,确保每个检测对象的特征表示是一致且最优的。本文所做出的改进是将YOLOv5的检测头更换…

程序算法设计分析

动态规划和分治、贪心相比有什么区别&#xff1f;各自的优缺点&#xff1f; 分治算法特征&#xff1a; 1&#xff09;规模如果很小&#xff0c;则很容易解决。//一般问题都能满足 2&#xff09;大问题可以分为若干规模小的相同问题。//前提 3&#xff09;利用子问题的解&#x…

O2OA(翱途)开发平台 V9.1 即将发布,更安全、更高效、更开放

尊敬的O2OA(翱途)平台合作伙伴、用户以及亲爱的开发小伙伴们&#xff0c;O2OA(翱途)平台 V9.1将于7月3日正式发布&#xff0c;届时欢迎大家到O2OA官网部署下载及体验最新版本。新版本我们在如下方面做了更大的努力&#xff1a; 1.扩展数据库兼容性和功能范围&#xff1a;在O2OA…

基于Web技术的教育辅助系统设计与实现(SpringBoot MySQL)+文档

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

汽车电子工程师入门系列——CAN 规范系列通读

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

使用 rye 管理 python 依赖

rye 是使用 rust 实现的一个项目和包管理解决方案。 配置 pip 源 vim ~/.pip/pip.conf [global] index-url http://mirrors.cloud.tencent.com/pypi/simple/ trusted-host mirrors.cloud.tencent.com安装 rye cargo install --git https://github.com/mitsuhiko/rye rye配…

laravel Dcat Admin 入门应用(五)文件上传之OSS自定义上传

laravel Dcat Admin 入门应用&#xff08;五&#xff09;文件上传之OSS自定义上传 Dcat Admin 是一个基于 Laravel-admin 二次开发而成的后台构建工具&#xff0c;只需很少的代码即可构建出一个功能完善的高颜值后台系统。支持页面一键生成 CURD 代码&#xff0c;内置丰富的后台…

使用ps给gif动图抠图

目录 导入gif图片 打开时间轴 选择图片 魔棒抠图-初步抠图 套索抠图-精准抠图 导入gif图片 打开时间轴 因为gif动图实际上多张图片实现的效果&#xff0c;所以如果要给gif抠图&#xff0c;就得挨个给每个时间线的图片抠图 点击窗口->时间轴 选择图片 在时间轴上选择要…

以 Vue 3 项目为例,多个请求下如何全局封装 Loading 的展示与关闭?其中大有学问!

大家好,我是CodeQi! 项目开发中,Loading 的展示与关闭是非常关键的用户体验设计。 当我们的应用需要发起多个异步请求时,如何有效地管理全局 Loading 状态,保证用户在等待数据加载时能有明确的反馈,这是一个值得深入探讨的问题。 本文将以 Vue 3 项目为例,详细讲解如…

eventloop 事件循环机制 (猜答案)

// eventloop 事件循环机制// console.log(555);setTimeout(() > {console.log(666);})let p new Promise((resolve,reject)>{// 同步执行console.log(111);resolve();});// promise 的回调函数是异步的微任务p.then(v > {console.log(222);}, r > {console.log(r…