详解Redisson

news2024/10/6 5:59:31

第1章:Redisson简介

大家好,我是小黑,咱们今天来聊聊Redisson,Redisson不只是简单地对Redis进行了封装,它还提供了一系列高级的分布式Java数据结构,像是分布式锁、原子长整型这种。

首先,Redisson的核心特点是什么呢?它提供了对Redis的各种操作的高层封装,这让咱们在使用Redis时更加方便、高效。再加上Redisson支持多种编码模式,比如JSON、Avro、Smile等,使得它非常灵活。

再说说应用场景。Redisson在Java中的应用非常广泛,无论是做缓存、实现分布式锁,还是构建消息队列,Redisson都能派上用场。尤其在处理高并发、数据一致性这些问题时,Redisson表现得尤为出色。

那Redisson究竟如何使用呢?来看个简单的例子。比如咱们要连接Redis服务器,用Redisson来操作一下:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class RedissonDemo {
    public static void main(String[] args) {
        // 创建配置对象
        Config config = new Config();
        // 指定使用单节点部署方式
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        // 创建Redisson客户端实例
        RedissonClient redisson = Redisson.create(config);
        
        // 这里可以进行相关操作,比如...
        
        // 最后关闭Redisson客户端
        redisson.shutdown();
    }
}

这段代码展示了如何用Redisson连接到Redis服务器。咱们通过Config对象设置了Redis服务器的地址,然后创建了一个RedissonClient实例。这就是Redisson的基本用法,简单明了。

第2章:Redisson的架构与原理

接下来,咱们深入了解一下Redisson的架构和原理。Redisson的架构设计得相当巧妙,它利用了Redis的高性能特性,提供了一套丰富的Java并发工具。

Redisson的工作原理是这样的:它在Redis的基础上实现了Java的java.util.concurrent包中的接口,比如LockAtomicLong等。这意味着咱们可以像使用Java的并发工具那样,直接使用Redisson提供的这些工具,而底层的数据实际上是存储在Redis中的。

举个例子,来看看Redisson如何实现分布式锁:

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

public class DistributedLockDemo {
    public static void main(String[] args) {
        RedissonClient redisson = ... // 假设这是已经配置好的Redisson客户端

        // 获取一个锁对象,这个锁在Redis中的名字叫做"myLock"
        RLock lock = redisson.getLock("myLock");

        // 尝试获取锁
        lock.lock();
        try {
            // 执行一些操作...
        } finally {
            // 释放锁
            lock.unlock();
        }
    }
}

这段代码演示了Redisson如何实现一个分布式锁。通过getLock方法,咱们获得了一个名为"myLock"的锁对象。接着,使用lock方法来加锁,完成操作后,再通过unlock方法释放锁。

第3章:Redisson的基本使用

连接Redis

要使用Redisson,咱们需要先连接到Redis服务器。这个步骤之前已经展示过了,但为了让内容完整,小黑再次演示一遍:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class ConnectRedis {
    public static void main(String[] args) {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);
        
        // 在这里执行操作...
        
        redisson.shutdown();
    }
}
基本操作

来看看基本操作。比如咱们想操作一个字符串:

import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;

public class StringOperation {
    public static void main(String[] args) {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        // 获取一个字符串对象,这里的"name"就是Redis中的key
        RBucket<String> bucket = redisson.getBucket("name");
        bucket.set("Redisson"); // 设置key对应的value为"Redisson"
        String value = bucket.get(); // 获取key对应的value
        
        System.out.println("获取到的值:" + value);
    }
}

高级数据结构操作

Redisson还支持许多高级的数据结构,比如队列、映射等。下面小黑给大家展示一下如何操作一个队列:

import org.redisson.api.RQueue;
import org.redisson.api.RedissonClient;

public class QueueOperation {
    public static void main(String[] args) {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        // 获取一个队列
        RQueue<String> queue = redisson.getQueue("myQueue");
        queue.add("一条消息"); // 往队列添加元素
        String item = queue.poll(); // 从队列获取并移除一个元素
        
        System.out.println("从队列中获取的元素:" + item);
    }
}

分布式锁的使用

Redisson的分布式锁也是它的一大特色。看看如何使用:

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

public class LockOperation {
    public static void main(String[] args) throws InterruptedException {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        RLock lock = redisson.getLock("myLock");
        lock.lock(); // 获取锁
        try {
            // 在这里执行同步操作...
        } finally {
            lock.unlock(); // 释放锁
        }
    }
}

通过这些例子,咱们可以看到,Redisson提供了一种非常直观和简洁的方式来操作Redis。不论是简单的键值操作,还是复杂的数据结构,Redisson都能让咱们轻松应对。而且,分布式锁的使用也变得非常简单,这对于处理分布式系统中的并发问题来说,简直是一大利器。

第4章:Redisson的高级特性

分布式数据结构

Redisson的一个亮点是提供了丰富的分布式数据结构,比如映射、集合、队列等。这些数据结构都是线程安全的,非常适合分布式系统中使用。

来看看如何使用分布式映射(Map):

import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;

public class DistributedMapExample {
    public static void main(String[] args) {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        // 创建一个分布式映射
        RMap<String, String> map = redisson.getMap("myMap");
        map.put("key1", "值1");
        map.put("key2", "值2");

        String value = map.get("key1");
        System.out.println("获取到的值:" + value);
    }
}

在这个例子中,咱们创建了一个名为myMap的分布式映射,并进行了简单的操作。这样的映射是跨多个Redisson实例的,也就是说,任何一个实例对映射的更改都会立即反映到其他实例上。

发布/订阅模型

Redisson还支持Redis的发布/订阅模型。这个功能非常适合构建消息系统,比如聊天室、实时通知等。

来看看怎么使用:

import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;

public class PubSubExample {
    public static void main(String[] args) {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        // 订阅主题
        RTopic topic = redisson.getTopic("myTopic");
        topic.addListener(String.class, new MessageListener<String>() {
            @Override
            public void onMessage(CharSequence channel, String msg) {
                System.out.println("收到消息:" + msg);
            }
        });

        // 发布消息
        topic.publish("Hello Redisson!");
    }
}

在这段代码中,咱们先订阅了一个名为myTopic的主题,然后发布了一条消息。当消息被发布时,所有订阅了这个主题的客户端都会收到这条消息。

延迟队列与阻塞队列

Redisson还提供了延迟队列和阻塞队列的实现,这对于构建复杂的消息系统或者任务调度系统非常有用。

import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;

import java.util.concurrent.TimeUnit;

public class QueueExample {
    public static void main(String[] args) throws InterruptedException {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        // 创建一个阻塞队列
        RBlockingQueue<String> blockingQueue = redisson.getBlockingQueue("myQueue");
        // 创建一个延迟队列
        RDelayedQueue<String> delayedQueue = redisson.getDelayedQueue(blockingQueue);

        // 往延迟队列添加元素,5秒后过期
        delayedQueue.offer("延迟消息", 5, TimeUnit.SECONDS);

        // 从阻塞队列中取元素,如果队列为空,则等待
        String element = blockingQueue.take();
        System.out.println("从队列中获取的元素:" + element);
    }
}

第5章:Redisson的分布式服务

分布式锁的实现与应用

在分布式系统中,处理并发问题是个大挑战。Redisson提供的分布式锁就是为了解决这个问题。我们先来回顾一下之前的分布式锁的例子,然后深入理解它的原理和应用。

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

public class DistributedLockExample {
    public static void main(String[] args) {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        RLock lock = redisson.getLock("myLock");
        lock.lock();
        try {
            // 执行同步操作
        } finally {
            lock.unlock();
        }
    }
}

在这个例子中,getLock方法获取了一个分布式锁。当多个实例尝试获取同一把锁时,只有一个实例能成功获得锁,并执行锁定的代码块。这保证了在分布式环境中操作的原子性和一致性。

分布式集合与映射

Redisson还提供了分布式集合和映射,这些数据结构在多个Redisson节点间是同步的。

import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;

public class DistributedCollectionsExample {
    public static void main(String[] args) {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        // 分布式列表
        RList<String> list = redisson.getList("myList");
        list.add("元素1");
        list.add("元素2");

        // 分布式映射
        RMap<String, String> map = redisson.getMap("myMap");
        map.put("键1", "值1");
        map.put("键2", "值2");
    }
}

在这段代码中,咱们操作了一个分布式列表和一个分布式映射。无论在哪个节点对这些数据结构进行操作,所有的更改都会反映到每个节点。

分布式计数器与原子操作

Redisson还提供了分布式计数器和原子操作,这对于在分布式系统中进行计数或同步更新是非常有用的。

import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;

public class DistributedAtomicLongExample {
    public static void main(String[] args) {
        RedissonClient redisson = ...; // 这是已经配置好的Redisson客户端

        // 分布式原子长整型
        RAtomicLong atomicLong = redisson.getAtomicLong("myAtomicLong");
        atomicLong.set(0);
        atomicLong.incrementAndGet(); // 自增并获取新值
        System.out.println("当前值:" + atomicLong.get());
    }
}

在这个例子中,getAtomicLong方法创建了一个分布式的原子长整型。这个计数器在所有Redisson实例之间是同步的,因此它可以在分布式系统中作为一个可靠的计数器使用。

第6章:Redisson与Spring Boot的整合

配置与依赖管理

首先,要在Spring Boot项目中使用Redisson,需要添加Redisson的依赖。在pom.xml中加入以下依赖:

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>最新版本</version>
</dependency>

接下来,配置Redisson。在application.yml或者application.properties文件中,添加Redis服务器的相关配置:

spring:
  redis:
    host: localhost
    port: 6379
缓存与事务管理

Redisson可以与Spring Boot的缓存抽象无缝整合。这意味着咱们可以非常简单地将Redisson作为Spring Boot应用的缓存解决方案。

例如,使用@Cacheable注解来缓存方法的结果:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Cacheable(value = "itemCache", key = "#id")
    public Item findItemById(Long id) {
        // 这里是模拟数据库查询操作
        return new Item(id, "Item名称");
    }
}

在这个例子中,findItemById方法的结果会被缓存起来。当相同的id再次调用该方法时,就会直接从缓存中获取结果,而不需要重新执行方法。

应用示例与最佳实践

现在来看一个具体的应用实例。假设咱们需要实现一个简单的基于Redis的分布式锁,来控制对共享资源的访问。

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class DistributedLockManager {

    @Autowired
    private RedissonClient redissonClient;

    public void performTaskWithLock(String lockName) {
        RLock lock = redissonClient.getLock(lockName);
        try {
            // 尝试获取锁,最多等待10秒,锁定后10秒自动解锁
            if (lock.tryLock(10, 10, TimeUnit.SECONDS)) {
                try {
                    // 执行业务操作
                } finally {
                    lock.unlock();
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

在这个例子中,我们通过注入的RedissonClient来获取一个分布式锁。通过tryLock方法来尝试获取锁,如果成功,就执行业务操作。

第7章:Redisson的性能优化与调优

参数调整与优化建议

在Redisson中,有几个关键参数是影响性能的:

  • 连接池大小:Redisson允许咱们配置连接池的大小。一个合理的连接池大小可以有效地提高资源利用率,减少因连接创建和销毁带来的开销。

  • 超时设置:合理的超时设置可以在网络延迟或者Redis服务器繁忙时避免应用挂起。但设置得太短可能会导致频繁的超时异常。

  • 序列化方式:Redisson支持多种序列化方式,比如JSON、Avro等。选择合适的序列化方式,可以减少网络传输的数据量,提高效率。

故障排查与解决方案

在使用Redisson时,可能会遇到一些问题,比如连接异常、性能下降等。这时,需要及时进行故障排查。

一般来说,排查步骤包括:

  • 查看日志:检查Redisson和应用的日志,看是否有异常信息。

  • 监控Redis服务器:使用Redis自带的监控工具,比如INFO命令,观察Redis的性能指标。

  • 网络问题:有时候问题可能是由网络引起的,这时可以使用网络监控工具进行检测。

为了更具体地理解,小黑举个例子。比如咱们发现Redisson的响应时间不稳定,经过排查发现是因为连接池太小。这时可以通过调整配置文件来增加连接池的大小:

spring:
  redis:
    redisson:
      single-server-config:
        connection-pool-size: 64 # 调整连接池大小

在进行调优时,建议逐步调整参数,并且持续进行性能测试,以确保每次调整都能带来正向的效果。

第8章:Redisson的实战案例分析

案例1:电商平台的库存管理

在电商平台中,库存管理是个大挑战。尤其在大促销时,高并发下的库存更新会非常复杂。

挑战:确保在高并发情况下,库存的准确性和一致性。

解决策略:使用Redisson的分布式锁来控制对库存的访问。当用户尝试购买商品时,先获取分布式锁,然后更新库存,最后释放锁。

代码示例

public class InventoryService {

    private final RedissonClient redissonClient;

    public InventoryService(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public boolean purchaseItem(String itemId) {
        RLock lock = redissonClient.getLock("inventory:" + itemId);
        try {
            if (lock.tryLock(10, 2, TimeUnit.SECONDS)) {
                // 检查并更新库存
                // ...
                return true;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
        return false;
    }
}

教训与经验:在高并发环境下,分布式锁是处理共享资源竞争的有效手段。但同时也要注意锁的粒度和超时时间,以免造成性能瓶颈。

案例2:实时消息推送系统

在一个需要实时消息推送的系统中,消息的及时传递至关重要。

挑战:如何高效地向大量用户推送实时消息。

解决策略:利用Redisson的发布/订阅功能实现消息的即时推送。当有消息需要推送时,将消息发布到特定的主题,所有订阅该主题的用户都能立刻收到消息。

代码示例

public class MessagePublisher {

    private final RedissonClient redissonClient;

    public MessagePublisher(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public void publishMessage(String topic, String message) {
        RTopic rTopic = redissonClient.getTopic(topic);
        rTopic.publish(message);
    }
}

教训与经验:发布/订阅模型非常适合实现实时消息系统,但要注意消息的序列化和网络延迟对性能的影响。

案例3:分布式定时任务

在分布式系统中,定时执行任务也是一个常见需求。

挑战:如何确保定时任务在分布式环境下的正确执行。

解决策略:使用Redisson的分布式定时任务功能。可以安排任务在指定时间执行,而且在多个节点中只会执行一次。

代码示例

public class SchedulerService {

    private final RedissonClient redissonClient;

    public SchedulerService(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public void scheduleTask(Runnable task, long delay, TimeUnit timeUnit) {
        RScheduledExecutorService executorService = redissonClient.getExecutorService("myScheduler");
        executorService.schedule(task, delay, timeUnit);
    }
}

教训与经验:分布式定时任务解决了在分布式系统中任务调度的难题,但需要注意任务执行的可靠性和失败重试机制。

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

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

相关文章

React 初次接触

背景 还是为了完善高大上的在线文档系统&#xff0c;虽然比着葫芦画瓢的修改了一些所谓的代码&#xff0c;慢慢的才发现&#xff0c;原来这就是传说中的React&#xff0c;所以有比较又要囫囵吞枣一下React。 基本原理 参照《React技术揭秘》 网上有电子版 &#xff0c;应该是…

Makefile编译原理 条件判断语句

一.makefile中支持条件判断语句 可以根据条件的值来决定make的执行 可以比较两个不同变量或者变量和常量值 条件判断语句语法说明&#xff1a; 条件判断关键字&#xff1a; 条件判断语句注意点&#xff1a; 条件判断语句之前可以有空格&#xff0c;但不能没有Tab字符&#x…

【Java】SpringBoot实现事件监听(异步执行)

在Spring Boot中&#xff0c;事件监听是一种机制&#xff0c;通过该机制&#xff0c;你可以定义和触发自定义的事件&#xff0c;以及在应用程序中注册监听器来响应这些事件&#xff0c;提供了一种解耦的方式来处理应用程序中的事件。 文末有源码gitee地址&#xff01;拉取可进…

MySQL基础笔记(8)多表查询

一.多表关系介绍 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也会存在着各种联系&#xff0c;分为如下3类&#xff1a; 一对…

【C++提高编程(二)】

一、STL初识 1.1、STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 大多情况下&#xff0c;数据结构和算法都未能有一套标准,导致被迫从事大量重复工作 为了建立数据结构和算法的一套标…

神经网络算法 —— 一文搞懂Transformer !!

文章目录 前言 一、Transformer的本质 1. Transformer架构 2. Encoder-Decoder&#xff08;编码器-解码器&#xff09; 二、Transformer的原理 1. Multi-Head Attention&#xff08;多头自注意力&#xff09; 2. Scaled Dot-Product Attention&#xff08;缩放点积注意力&#…

坦克大战游戏代码

坦克大战游戏 主函数战场面板开始界面坦克父类敌方坦克我方坦克子弹爆炸效果数据存盘及恢复图片 主函数 package cn.wenxiao.release9;import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JFrame; import javax.swing.JMenu; impor…

2024年【金属非金属矿山(地下矿山)安全管理人员】证考试及金属非金属矿山(地下矿山)安全管理人员模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员】证考试及金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员模拟考试题库&#xff0c;包含金属非金属矿山&#xff08;地下矿山&…

RabbitMQ-消息延迟

一、死信交换机 1、描述 一个队列接收到的消息有过期时间&#xff0c;消息过期之后&#xff0c;如果配置有死信队列&#xff0c;消息就会进去死信队列。 2、图解 3、过程 当生产者将消息发送到exchange1&#xff0c;然后交换机将消息路由到队列queue1&#xff0c;但是队列que…

探索指针的奇妙世界,程序中的魔法箭头(上)

目录 一.指针是什么二.指针和指针类型1.指针加减整数2.指针的解引用 三.野指针1.野指针形成的原因&#xff08;1&#xff09;指针未初始化指针越界访问 2.如何规避野指针&#xff08;1&#xff09;指针初始化&#xff08;2&#xff09;小心指针越界&#xff08;3&#xff09;指…

SpringSecurity+JWT前后端分离架构登录认证

目录 1. 数据库设计 2. 代码设计 登录认证过滤器 认证成功处理器AuthenticationSuccessHandler 认证失败处理器AuthenticationFailureHandler AuthenticationEntryPoint配置 AccessDeniedHandler配置 UserDetailsService配置 Token校验过滤器 登录认证过滤器接口配置…

理解PCIE设备透传

PCIE设备透传解决的是使虚拟机直接访问PCIE设备的技术&#xff0c;通常情况下&#xff0c;为了使虚拟机能够访问Hypervisor上的资源&#xff0c;QEMU&#xff0c;KVMTOOL等虚拟机工具提供了"trap and emulate"&#xff0c; Virtio半虚拟化等机制实现。但是这些实现都…

用通俗易懂的方式讲解:使用 Langchain 和 Hugging Face ,轻松实现大模型 RAG 用法

检索增强生成&#xff08;RAG&#xff09;是一种与预训练的大型语言模型&#xff08;LLM&#xff09;和自己的数据一起工作的模式&#xff0c;用于生成响应。 现在我将向大家介绍在代码中实现 RAG 的过程。让我们开始使用 Langchain 和 Hugging Face 实现 RAG&#xff01; 文章…

matlab appdesigner系列-常用14-树(复选框)

之前系列常用9&#xff0c;为单个复选框。树&#xff0c;就是多个复选框形成的选项组 示例&#xff1a;列举湖北省的几个城市 湖北省 武汉 宜昌 襄阳 荆州 1&#xff09;将树&#xff08;复选框&#xff09;拖拽到画布上&#xff0c;方式1就是&#xff1a;文字可以在右侧…

【线上问题】CompletableFuture与线程池使用不当导致服务整个挂掉

Informal Essay By English It is always a pleasure to learn 背景 在某一个风和日丽的早上&#xff0c;小组同事说昨晚线上服务有20分钟左右的不可用&#xff0c;当时内心一紧&#xff0c;不会是我写的代码有bug导致的吧&#x1f440;&#xff0c;我正了正心态&#xff0c…

[小程序]样式与配置

一、外部样式导入 使用import加外部样式表的相对路径并以 ; 表示语句结束。 import "common.wxss"; 二、全局样式和局部样式 全局样式位于app.wxss中&#xff0c;会作用于整个项目中所有页面中。 局部样式位于对应的wxss文件中&#xff0c;仅作用于当前页面&#x…

WebDriverWait太强大

selenium webdriver及wait 1 implicitly包打天下2 Linkedin无法登录返回值很乱&#xff0c;怎么破&#xff1f; 1 implicitly包打天下 有了implicitly之后&#xff0c;基本上不再关注网速之类的影响。 self.driver.implicitly_wait(511)2 Linkedin无法登录返回值很乱&#xf…

Vulnhub-TECH_SUPP0RT: 1渗透

文章目录 一、前言1、靶机ip配置2、渗透目标3、渗透概括 开始实战一、信息获取二、使用smb服务获取信息三、密码破解四、获取webshell五、反弹shell六、web配置文件获取信息七、提权 一、前言 由于在做靶机的时候&#xff0c;涉及到的渗透思路是非常的广泛&#xff0c;所以在写…

ad18报错:clearance constraint

最常见的报错&#xff0c;直译过来的意思&#xff1a;间隙约束。也就是约束PCB中的电气间距&#xff0c;比如阻容各类元件的焊盘间距小于规则中的设定值&#xff0c;即报警。 Altium Designer 中的 Clearance Constraint 错误如何修改-CSDN博客 【Altium Designer21】DRC规则…

Vulnhub靶机:FunBox 2

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;FunBox 2&#xff08;10.0.2.27&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://download.vulnhub.com/funbo…