Redis 缓存雪崩、穿透、击穿、预热

news2025/1/16 11:14:47

        在实际工程中,Redis 缓存问题常伴随高并发场景出现。例如,电商大促、活动报名、突发新闻时,由于缓存失效导致大量请求访问数据库,导致雪崩击穿穿透等问题。因此,新系统上线前需预热缓存,以应对高并发,减轻数据库压力。本章主要围绕这几个核心问题,针对产生场景、分析原因、并给出相应的解决方案。

常见问题:

1. 缓存穿透

1.1 什么是缓存穿透

一句话,就是查询一条根本没有的记录。它既不存在于redis中,也不存在数据库中。一般我们的查询顺序是先查redis、再查数据库。每次请求最终都会访问到数据库。造成数据库访问压力。这种现象叫缓存穿透

问题描述
        key 对应的数据在数据源并不存在,每次针对此 key 的请求从缓存获取不到,请求都会压到数据源(数据库),从而可能压垮数据源。比如用一个不存在的用户 id 获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。

1.2 产生原因

  • 查询记录在redis和数据库均不存在

  • 恶意攻击

缓存穿透发生的条件:

  • 应用服务器压力变大
  • redis 命中率降低
  • 一直查询数据库,使得数据库压力太大而压垮

其实 redis 在这个过程中一直平稳运行,崩溃的是我们的数据库(如 MySQL)。

缓存穿透发生的原因:黑客或者其他非正常用户频繁进行很多非正常的 url 访问,使得 redis 查询不到数据库。

1.3 解决方案

方案一:使用布隆过滤器

使用布隆过滤器解决缓存穿透问题具体流程如下:

流程说明:

  • Web端发起请求到App服务应用

  • 经过布隆过滤器判断key是否存在

  • 若不存在,直接返回null

  • 若key存在或者被误判(下文详述),查询redis

  • 若redis中有结果,直接返回

  • 未查到,则查询数据库返回结果

  • 数据库查到结果,返回结果。并将对应key回写redis

  • 未查到,则返回null

方案二:缓存空对象或者默认值

针对要查询的数据,需求层面沟通,可以在Redis里存一个缺省值(比如,零、负数、defaultNull等)。

流程描述:

  • 先去redis查键user:xxxxxx没有,再去mysql查没有获得 ,这就发生了一次穿透现象;

  • 第一次来查询user:xxxxxx,redis和mysql都没有,返回null给调用者;

  • 将 user:xxxxxx,defaultNull 回写redis;

  • 第二次查user:xxxxxx,此时redis就有值了。

可以直接从Redis中读取default缺省值返回给业务应用程序,避免了把大量请求发送给mysql处理,打爆mysql。

但是,此方法只能解决key相同的情况,但是无法应对黑客恶意攻击。

解决方案:

  • 对空值缓存:如果一个查询返回的数据为空(不管是数据是否不存在),我们仍然把这个空结果(null)进行缓存,设置空结果的过期时间会很短,最长不超过五分钟。
  • 设置可访问的名单(白名单):使用 bitmaps 类型定义一个可以访问的名单,名单 id 作为 bitmaps 的偏移量,每次访问和 bitmap 里面的 id 进行比较,如果访问 id 不在 bitmaps 里面,进行拦截,不允许访问。
  • 采用布隆过滤器:布隆过滤器(Bloom Filter)是 1970 年由布隆提出的。它实际上是一个很长的二进制向量 (位图) 和一系列随机映射函数(哈希函数)。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
  • 进行实时监控:当发现 Redis 的命中率开始急速降低,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名单限制服务。

2. 缓存击穿

2.1 什么是缓存击穿

一句话,就是热点key突然失效了,大量请求暴击数据库。关键词:大量请求、同一个热点key、正好失效。

问题描述
        key 对应的数据存在,但在 redis 中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端数据库加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端数据库压垮。

2.2 产生原因(发生场景)

  • 某个key以到过期时间,但是还是被访问到

  • key被删除,但是被访问到

  • 如,某电商网站的今日特卖

缓存击穿的现象:
数据库访问压力瞬时增加,数据库崩溃
redis 里面没有出现大量 key 过期
redis 正常运行
缓存击穿发生的原因:redis 某个 key 过期了,大量访问使用这个 key(热门 key)。

2.3 解决方案

方案一:差异失效时间

差异失效时间,对于访问频繁的热点key,不设置过期时间。和上边类似,这里不再赘述。

方案二:采用互斥锁,双检加锁策略更新

 双检锁通常用于解决懒加载中的并发问题,即只有当数据在缓存中不存在时,才进行数据库查询,并且确保只有一个线程进行数据库查询。

基本流程如下:

  1. 当大量请求进来,多个线程同时去查询数据库获取同一条数据;

  2. 在第一个查询数据的请求上使用一个互斥锁来锁定;

  3. 其他的线程走到这一步拿不到锁排队等着;

  4. 第一个线程查询到了数据,然后做缓存;

  5. 后面的线程进来发现已经有缓存了,就直接走缓存。

解决方案
        key 可能会在某些时间点被超高并发地访问,是一种非常 “热点” 的数据。

预先设置热门数据:在 redis 高峰访问之前,把一些热门数据提前存入到 redis 里面,加大这些热门数据 key 的时长。
实时调整:现场监控哪些数据热门,实时调整 key 的过期时长。
使用锁:
就是在缓存失效的时候(判断拿出来的值为空),不是立即去 load db。
先使用缓存工具的某些带成功操作返回值的操作(比如 Redis 的 SETNX)去 set 一个 mutex key。
当操作返回成功时,再进行 load db 的操作,并回设缓存,最后删除 mutex key;
当操作返回失败,证明有线程在 load db,当前线程睡眠一段时间再重试整个 get 缓存的方法。

3. 缓存雪崩

3.1 什么是缓存雪崩

指在一个高并发的系统中,由于大量的缓存数据在同一时间段内过期或失效,导致大量请求无法从缓存中获取数据,因此大量并发请求可能导致数据库服务器过载,甚至宕机,从而引发整个系统崩溃。

问题描述
        key 对应的数据存在,但在 redis 中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端数据库加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端数据库压垮。

        缓存雪崩与缓存击穿的区别在于这里针对很多 key 缓存,前者则是某一个 key 正常访问。

3.2 产生原因

  • 硬件故障。 比如:机房着火、停电等导致redis挂机
  • 软件设计。redis中有大量key同时过期或者大面积失效。导致缓存中查不到对应key。此时访问压力给到数据库。如图示:

实际应用场景中,如:

  • 金融系统股票价格、汇率等数据实时变动;

  • 热点新闻缓存过期时,大量用户访问新闻详情页的请求;

  • 电商平台在大促期间,如“618”、“双十一”等。

  如果这些数据在缓存中的过期时间设置得过于集中,或者缓存服务器突然宕机,那么在数据过期或缓存失效的瞬间,大量请求会直接访问数据库,导致数据库负载剧增,可能引发雪崩

3.3 解决方案

针对雪崩问题的解决方案,一般可以从以下几个角度考虑:

方案一:设置redis的某些key永不过期

简单地使用 SET 命令来添加这个key,不需要调用任何设置过期时间的命令:

SET product:500100 "{\"name\":\"ProductName\", \"price\":99.99, \"status\":\"上架中\"}"

在java中,可以使用Jedis或者RedisTemplate客户端

redisTemplate.opsForValue().set(productCode, productData);

  值得注意的是,可能因为Redis的内存限制或其他原因(如使用了Redis的LRU淘汰策略)而被删除。因此,在设计系统时,除了考虑key的过期时间外,还需要考虑Redis的内存管理和淘汰策略。

方案二:搭建高可用redis集群+持久化

如图,一般线上环境都会有redis集群保证高可用。

图片

对应集群模式:

  • 主从模式(Master-Slave)

  • 哨兵模式 (Sentinel)

  • 分片模式 (Cluster)

关于三种集群模式的优缺点对比,配置这里不再赘述。图示只说明redis集群保障高可用的能力。

方案三:服务降级、熔断、限流

在Spring Cloud中使用Hystrix和Sentinel进行熔断降级和限流,这里给出简单的程序示例。

  • 服务熔断降级 - Hystrix

配置pom.xml

<dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>  
</dependency>

在启动类上添加@EnableHystrix注解来启用Hystrix。

@SpringBootApplication
@EnableHystrix
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

在服务调用方法上添加@HystrixCommand注解,并配置相应的降级逻辑。

@Service
public class MyService {

    @HystrixCommand(fallbackMethod = "fallbackMyMethod")
    public String busiMethod() {
        // 调用远程服务
    }

    public String fallbackMyMethod() {
        // 降级逻辑
        return "Fallback response";
    }
}

对于Hystrix的YML配置,你可以在application.ymlapplication.properties中设置一些全局参数,例如超时时间、请求缓存等。

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000 # 设置命令执行的超时时间
      fallback:
        enabled: true # 启用降级逻辑
  • 限流 - Sentinel

pom.xml中添加了Sentinel的依赖。

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

在启动类上添加@EnableDiscoveryClient@EnableSentinel注解。

@SpringBootApplication
@EnableDiscoveryClient
@EnableSentinel
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Sentinel的限流规则通常不是在YML文件中配置的,而是通过Sentinel Dashboard进行动态配置。这里设置一些基础配置,例如数据源等。

application.yml中,你可以配置Sentinel的数据源类型以及Dashboard的地址。

spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080 # Sentinel Dashboard的地址
      datasource:
        flow:
          default:
            type: file
            file:
              file-name: classpath:flow-rules.json # 规则文件路径
            rule-type: flow

需要创建一个规则文件,例如flow-rules.json,并在其中定义限流规则。

[
    {
        "resource": "some-resource",
        "count": 10,
        "grade": 1,
        "limitApp": "default",
        "strategy": 0
    }
]

  这里我们针对some-resource的QPS限流规则,允许每秒最多10个请求。Sentinel的主要优势在于其动态规则管理能力,因此通常建议通过Sentinel Dashboard进行实时配置和监控。

当然,对于限流,也可以在网关层面使用Spring Cloud Gateway实现。如下图:

图片

  Spring Cloud Gateway是分布式系统中流量的入口。它需要对大量的请求进行管理和控制,以防止服务调用失败(如超时、异常)导致的请求堆积在网关上。通过在网关层面进行限流,可以快速失败并返回给客户端,从而保护后端服务的稳定性。

方案四:设计多级缓存架构

多级缓存主要从:redis缓存本地缓存Nginx缓存考虑

构建多级缓存架构:nginx 缓存 + redis 缓存 + 其他缓存(ehcache 等)。
使用锁或队列:用加锁或者队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上,该方法不适用高并发情况。
设置过期标志更新缓存:记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际 key 的缓存。
将缓存失效时间分散开:比如可以在原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

4. 缓存预热

缓存预热是一种缓存优化技术,其核心思想是在系统上线或服务重启之前,提前将相关的缓存数据加载到缓存系统中。这样做的目的是为了避免在实际请求到达时进行缓存项的加载,从而减少了响应时间,提升了系统的性能。

以下是一些常见的缓存预热实现方案:

方案一:批量预加载数据

在系统启动或服务重启时,可以批量查询数据库并将结果存入缓存中。这种方式适用于数据量相对固定且比较小的情况。比如:常用的字典配置信息。

public void preloadCache() {
    List<String> keys = ... // 获取需要预热的缓存键列表
    for (String key : keys) {
        Object value = dao.get(key); // 从数据库中获取数据
        if (value != null) {
            redis.set(key, serialize(value), cacheExpiration); // 将数据存入缓存
        }
    }
}

方案二:异步预热

 如果预热的数据量很大,或者预热过程比较耗时,可以考虑使用异步任务来执行预热操作。这样可以避免阻塞系统启动,并且可以利用系统的空闲时间来预热缓存。

@PostConstruct
public void startPreloadCacheAsync() {
    CompletableFuture.runAsync(() -> preloadCache());
}

方案三:定时任务预热

对于某些周期性变化的数据,可以用定时任务来定期预热缓存。例如,对于每天更新的数据,可以在每天的某个固定时间执行预热操作。

@Scheduled(fixedRate = 24 * 60 * 60 * 1000) // 每天执行一次
public void schedulePreloadCache() {
    preloadCache();
}

方案四、使用SpringBoot InitializingBean接口实现

下面是一个使用InitializingBean接口实现缓存预热的示例:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class CachePreloader implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        // 获取需要预热的缓存键列表
        List<String> keysToPreload = ...; 
        for (String key : keysToPreload) {
           // 从数据源获取数据
            Object value = dbService.get(key); 
            if (value != null) {
                // 将数据放入缓存
                cacheService.put(key, value);
            }
        }
    }
}

总结:

本文主要介绍了redis缓存使用中常见的问题:缓存雪崩、缓存击穿、缓存穿透、缓存预热等。详情归纳如下:

缓存问题产生原因解决方案
缓存雪崩大量缓存失效,导致数据库过载1. 分散缓存失效时间
2. 多级缓存
3. 缓存高可用
4. 服务降级限流
缓存穿透查询不存在的数据,导致数据库过载1. 布隆过滤器
2. 空值缓存
缓存击穿热点数据失效,导致数据库过载1. 热点数据永不过期
2. 使用互斥锁

关于热点数据:

Redis中的热点数据是指在一段时间内访问频次极高、热度很高的数据。这些数据在短时间内被大量请求访问,成为整个Redis缓存系统中被频繁查询或更新的对象。热点数据的特点是访问集中在少数几个Key上,可能导致以下几个问题:

  1. 缓存命中率下降:热点数据如果在缓存中失效,短时间内大量请求涌向数据库以获取该数据,缓存命中率急剧下降,增加了数据库的压力。

  2. 缓存雪崩风险:如果热点数据集中设置了相同的过期时间,过期后同时失效,可能会引发缓存雪崩效应,即大量请求瞬间落库,可能导致数据库不堪重负。

  3. 缓存穿透:在极端情况下,热点数据频繁访问的同时,如果该数据恰巧不在缓存中或者已经被移除,每一条请求都会直接穿透缓存到达数据库,加重数据库的负载。

为了避免和优化热点数据带来的问题,可以采取以下策略:

  • 延长热点数据的缓存有效期:适当延长热点数据在缓存中的存活时间,以减少数据库查询的次数。
  • 使用互斥锁:在更新热点数据时使用分布式锁,确保数据更新时的一致性和完整性,避免频繁更新导致的缓存失效问题。
  • 缓存预热:预测和主动加载热点数据到缓存中,确保在高峰期到来之前数据已经存在于缓存中。
  • 缓存淘汰策略优化:选用合适的淘汰策略,例如Redis的LFU(Least Frequently Used)策略可以优先保留访问频次最高的数据,即热点数据。
  • 数据分片与扩容:如果热点数据集中度非常高,可以考虑将热点数据单独存储或分片存储,并根据访问情况进行动态扩容。

总之,妥善管理和优化Redis中的热点数据对于维持系统性能和稳定性至关重要。

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

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

相关文章

RabbitMQ3.x之九_Docker中安装RabbitMQ

RabbitMQ3.x之_Docker中安装RabbitMQ 文章目录 RabbitMQ3.x之_Docker中安装RabbitMQ1. 官网2. 安装1 .拉取镜像2. 运行容器 3. 访问 1. 官网 rabbitmq - Official Image | Docker Hub 2. 安装 1 .拉取镜像 docker pull rabbitmq:3.13.0-management2. 运行容器 # latest Rabb…

LLM端侧部署系列 | 如何将阿里千问大模型Qwen部署到手机上?实战演示(下篇)

引言 简介 编译Android可用的模型 转换权重 生成配置文件 模型编译 编译apk 修改配置文件 绑定android library 配置gradle 编译apk 手机上运行 安装 APK 植入模型 效果实测 0. 引言 清明时节雨纷纷&#xff0c;路上行人欲断魂。 小伙伴们好&#xff0c;我是《小…

iOS-App:App Store新的审核政策,在应用隐私清单中声明和解释使用特定API的原因

App Store新的审核政策&#xff0c;在应用隐私清单中声明和解释使用特定API的原因 设备/引擎&#xff1a;Mac&#xff08;11.6&#xff09;/Mac Mini 开发工具&#xff1a;终端 开发需求&#xff1a;苹果官方邮件通知&#xff0c; App Store新的审核政策&#xff0c;在应用隐…

Transformer学习: Transformer小模块学习--位置编码,多头自注意力,掩码矩阵

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Transformer学习 1 位置编码模块1.1 PE代码1.2 测试PE1.3 原文代码 2 多头自注意力模块2.1 多头自注意力代码2.2 测试多头注意力 3 未来序列掩码矩阵3.1 代码3.2 测试掩码 1 …

绿联 安装halo博客,使用MySQL数据库

绿联 安装halo博客&#xff0c;使用MySQL数据库 1、镜像 halohub/halo:2 halo2系列已支持halohub/halo:2直接拉取最新版本&#xff0c;因此更新容器可以使用相同镜像重新编辑的方式进行升级。 安装前准备&#xff1a; 绿联 安装Mysql 5.7版本数据库 绿联 安装phpmyadmin管理M…

基本线段树以及相关例题

1.线段树的概念 线段树是一种二叉树&#xff0c;也就是对于一个线段&#xff0c;我们会用一个二叉树来表示。 这个其实就是一个线段树&#xff0c;我们会将其每次从中间分开&#xff0c;其左孩子就是左边的集合的和&#xff0c;其右孩子就是右边集合的和&#xff1b; 我们可以…

VSCode常用修改默认设置(settings.json)

❓ 问题1 我现在在vscode中鼠标选中某个单词&#xff0c;相同的单词都会自动出现一个高亮背景色&#xff0c;我需要怎么关闭这个功能呢&#xff1f; ⚠️ 注意 selectionHighlight 这个是鼠标双击后的高亮匹配&#xff0c;可以保留默认开启的配置&#xff0c;不用去改它。 …

力扣每日一题:LCR112--矩阵中的最长递增路径

题目 给定一个 m x n 整数矩阵 matrix &#xff0c;找出其中 最长递增路径 的长度。 对于每个单元格&#xff0c;你可以往上&#xff0c;下&#xff0c;左&#xff0c;右四个方向移动。 不能 在 对角线 方向上移动或移动到 边界外&#xff08;即不允许环绕&#xff09;。 示例…

前端入门系列-HTML-HTML结构

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” HTML基础 HTML结构 认识HTML标签 HTML代码是由“标签”构成的。 形如 <body>hello </body> 标签名&#xff08;body&#xff09;放到<>中大部分标签成对…

见证历史:Quantinuum与微软取得突破性进展,开启了可靠量子计算的新时代!

Quantinuum与微软的合作取得了重大突破&#xff0c;将可靠量子计算带入了新的时代。他们结合了Quantinuum的System Model H2量子计算机和微软创新的量子比特虚拟化系统&#xff0c;在逻辑量子比特领域取得了800倍于物理电路错误率的突破。这一创新不仅影响深远&#xff0c;加速…

C#仿OutLook的特色窗体设计

目录 1. 资源图片准备 2. 设计流程&#xff1a; &#xff08;1&#xff09;用MenuStrip控件设计菜单栏 &#xff08;2&#xff09;用ToolStrip控件设计工具栏 &#xff08;3&#xff09;用StatusStrip控件设计状态栏 &#xff08;4&#xff09;ImageList组件装载树节点图…

【ORB-SLAM3】Ubuntu20.04 使用 RealSense D435i 运行 ORB-SLAM3 时遇到的一些 Bug

【ORB-SLAM3】使用 RealSense D435i 跑 ORB-SLAM3 时遇到的一些 Bug 1 hwmon command 0x80( 5 0 0 0 ) failed (response -7 HW not ready)2 No rule to make target /opt/ros/noetic/lib/x86_64-linux-gnu/librealsense2.so, needed by ../lib/libORB_SLAM3.so 1 hwmon comman…

微信小程序 python+django口腔牙科问诊系统 springboot设计与实现_1171u

口腔助手”小程序主要有管理员&#xff0c;医生和用户三个功能模块。以下将对这三个功能的作用进行详细的剖析。 本文通过采用B/S架构&#xff0c;uniapp框架、MySQL数据库&#xff0c;结合国内“口腔助手”管理现状&#xff0c;开发了一个基于微信小程序的“口腔助手”小程序。…

基于ArrayList实现简单洗牌

前言 在之前的那篇文章中&#xff0c;我们已经认识了顺序表—>http://t.csdnimg.cn/2I3fE 基于此&#xff0c;便好理解ArrayList和后面的洗牌游戏了。 什么是ArrayList? ArrayList底层是一段连续的空间&#xff0c;并且可以动态扩容&#xff0c;是一个动态类型的顺序表&…

二、企业级架构之Nginx

一、Nginx的重装与升级 1、为什么需要重装与升级&#xff1a; 在实际业务场景中&#xff0c;需要使用软件新版本的功能、特性&#xff0c;就需要对原有软件进行升级或者重装操作。 Nginx&#xff1a;1.12版本 → 1.16版本 2、Nginx重装&#xff1a; 第一步&#xff1a;停止…

linux操作系统的进程状态

这个博客只是为了自己复习用的&#xff01;&#xff01;&#xff01; 冯诺依曼体系结构 计算机是由一个一个硬件组成的 输入设备&#xff1a;键盘&#xff0c;鼠标&#xff0c;扫描仪&#xff0c;写板等等 中央处理器&#xff08;CPU&#xff09;:含有运算器和控制器等 输出单…

Vue-05

v-model 应用于其他表单元素 常见的表单元素都可以用v-model绑定关联 → 快速获取或设置表单元素的值 它会根据控件类型自动选取正确的方法来更新元素 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name…

树莓派部署yolov5实现目标检测(ubuntu22.04.3)

最近两天搞了一下树莓派部署yolov5&#xff0c;有点难搞&#xff08;这个东西有点老&#xff0c;版本冲突有些包废弃了等等&#xff09; 最后换到ubuntu系统弄了&#xff0c;下面是我的整体步骤&#xff08;建议先使能一下ssh&#xff08;最下面有&#xff09;&#xff0c;结合…

Macbook文件清理软件 Mac电脑清理垃圾文件怎么清理

为了维护Macbook电脑的系统健康&#xff0c;我们需要定期给电脑进行全面清理&#xff0c;清除系统垃圾文件、软件缓存和系统内存。那么好用的Macbook文件清理软件有哪些呢&#xff1f;今天就给大家介绍几款好用的电脑清理软件并介绍Mac电脑清理垃圾文件怎么清理。 一、Macbook…

RPA自动化小红书自动化写文以及发文!

1、视频演示 RPA自动化小红书自动写作发文 2、核心功能点 采集笔记&#xff1a;采集小红书上点赞量大于1000的爆款笔记 下载素材&#xff1a;下载爆款笔记的主图 爆款改写&#xff1a;根据爆款笔记的标题仿写新的标题以及新的文案 自动发布&#xff1a;将爆款笔记发布到小红…