七、Redis 缓存 —— 超详细操作演示!

七、Redis 缓存 —— 超详细操作演示!

    • 七、Redis 缓存
      • 7.1 Jedis 客户端
          • 7.1.1 Jedis 简介
          • 7.1.2 创建工程
          • 7.1.3 使用 Jedis 实例
          • 7.1.4 使用 JedisPool
          • 7.1.5 使用 JedisPooled
          • 7.1.6 连接 Sentinel 高可用集群
          • 7.1.7 连接分布式系统
          • 7.1.8 操作事务
      • 7.2 金融产品交易平台
      • 7.3 高并发问题
          • 7.3.1 缓存穿透
          • 7.3.2 缓存击穿
          • 7.3.3 缓存雪崩
          • 7.3.4 数据库缓存双写不一致

数据库系列文章:

关系型数据库:

  • MySQL —— 基础语法大全
  • MySQL —— 进阶


非关系型数据库:

  • 一、Redis 的安装与配置
  • 二、Redis 基本命令(上)
  • 三、Redis 基本命令(下)
  • 四、Redis 持久化
  • 五、Redis 主从集群
  • 六、Redis 分布式系统

七、Redis 缓存

7.1 Jedis 客户端

7.1.1 Jedis 简介

    Jedis 是一个 基于 java 的 Redis 客户端连接工具 ,旨在提升性能易用性 。 其 github 上的官网地址为: https://github.com/redis/jedis 。

7.1.2 创建工程

    首先创建一个普通的 Maven 工程 01-jedis ,然后在 POM 文件中添加 Jedis 与 Junit 依赖。

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
	<maven.compiler.source>1.8</maven.compiler.source> 
	<maven.compiler.target>1.8</maven.compiler.target> 
</properties> 

<dependencies> 
	<!--jedis依赖--> 
	<dependency> 
		<groupId>redis.clients</groupId> 
		<artifactId>jedis</artifactId> 
		<version>4.2.0</version> 
	</dependency> 

	<dependency> 
		<groupId>junit</groupId> 
		<artifactId>junit</artifactId> 
		<version>4.11</version> 
		<scope>test</scope> 
	</dependency> 
</dependencies>
7.1.3 使用 Jedis 实例

    Jedis 基本使用十分简单, 其提供了非常丰富的操作 Redis 的方法,而这些方法名几乎与 Redis 命令相同。 在每次使用时直接创建 Jedis 实例即可。在 Jedis 实例 创建好之后, Jedis 底层实际会创建一个到指定 Redis 服务器Socket 连接 。所以 ,为 了节省系统资源网络带宽 在每次使用完 Jedis 实例 之后,需要立即调用 close() 方法将 连接关闭。

    首先,需要在工程的 src/test/java 下创建测试类 JedisTest

⭐️(1) value 为 String 的测试

@Test
public void test01() {
    Jedis jedis = new Jedis("redis", 6379);
    jedis.set("name", "张三");
    jedis.mset("age", "23", "depart", "市场部");

    System.out.println("name = " + jedis.get("name"));
    System.out.println("age = " + jedis.get("age"));
    System.out.println("depart = " + jedis.get("depart"));
    
    jedis.close();
}

在这里插入图片描述
在这里插入图片描述

⭐️(2) value 为 Hash 的测试

@Test
public void test02() {
    Jedis jedis = new Jedis("redis", 6379);
    jedis.hset("emp", "name", "Tom");

    Map<String, String> map = new HashMap<>();
    map.put("age", "24");
    map.put("depart", "行政部");
    jedis.hset("emp", map);

    System.out.println("emp.name = " + jedis.hget("emp", "name"));
    List<String> emp = jedis.hmget("emp", "name", "age", "depart");
    System.out.println("emp = " + emp);

    jedis.close();
}

在这里插入图片描述

⭐️(3) value 为 List 的测试

// value为List的情况
@Test
public void test03() {
    Jedis jedis = new Jedis("redis", 6379);
    jedis.rpush("cities", "北京", "上海", "广州");
    List<String> cities = jedis.lrange("cities", 0, -1);
    System.out.println("cities = " + cities);

    jedis.close();
}

在这里插入图片描述

⭐️(4) value 为 Set 的测试

// value为Set的情况
@Test
public void test04() {
    Jedis jedis = new Jedis("redis", 6379);
    jedis.sadd("courses", "Redis", "RocketMQ", "Zookeeper", "Kafka");
    Set<String> courses = jedis.smembers("courses");
    System.out.println("courese = " + courses);

    jedis.close();
}

在这里插入图片描述

⭐️(5) value 为 Zset 的测试

// value为ZSet的情况
@Test
public void test05() {
    Jedis jedis = new Jedis("redis", 6379);
    jedis.zadd("sales", 50, "Benz");
    jedis.zadd("sales", 40, "BMW");
    jedis.zadd("sales", 30, "Audi");
    jedis.zadd("sales", 80, "Tesla");
    jedis.zadd("sales", 120, "BYD");

    List<String> top3 = jedis.zrevrange("sales", 0, 2);
    System.out.println("top3 = " + top3);

    List<Tuple> sales = jedis.zrevrangeWithScores("sales", 0, -1);
    for (Tuple sale : sales) {
        System.out.println(sale.getScore() + ":" + sale.getElement());
    }

    jedis.close();
}

在这里插入图片描述

7.1.4 使用 JedisPool

    如果应用非常 频繁地 创建和销毁 Jedis 实例 虽然节省了系统资源与网络带宽,但会大大降低系统性能。 因为 创建和销毁 Socket 连接 是比较耗时的 。 此时可以使用 Jedis 连接池 来解决该问题。

    使用 JedisPool 与使用 Jedis 实例的区别是, JedisPool全局性的整个类只需创建一次即可,然后每次需要操作 Redis 时,只需从 JedisPool 中拿出一个 Jedis 实例 直接使用即可。使用完毕后,无需释放 Jedis 实例,只需 返回 JedisPool 即可。

public class JedisPoolTest {

    private JedisPool jedisPool = new JedisPool("redis", 6379);

    // value为String的情况
    @Test
    public void test01() {
        try(Jedis jedis = jedisPool.getResource()) {
            jedis.set("name", "张三");
            jedis.mset("age", "23", "depart", "市场部");

            System.out.println("name = " + jedis.get("name"));
            System.out.println("age = " + jedis.get("age"));
            System.out.println("depart = " + jedis.get("depart"));
        }
    }
}

在这里插入图片描述

7.1.5 使用 JedisPooled

    对于每次对 Redis 的操作都需要使用 try-with-resource 块是比较麻烦的,而使用 JedisPooled 则无需再使用该结构来自动释放资源了。

public class JedisPooledTest {
   
   private JedisPooled jedis = new JedisPooled("192.168.216.128", 6379);

    // value为String的情况
    @Test
    public void test01() {
        jedis.set("name", "张三");
        jedis.mset("age", "23", "depart", "市场部");

        System.out.println("name = " + jedis.get("name"));
        System.out.println("age = " + jedis.get("age"));
        System.out.println("depart = " + jedis.get("depart"));
    }
}

在这里插入图片描述

7.1.6 连接 Sentinel 高可用集群

    对于 Sentinel 高可用集群的连接,直接使用 JedisSentinelPool 即可。在该客户端只需注册所有 Sentinel 节点 及其监控的 Master 的名称即可,无需出现 master -slave 的任何地址信息。其采用的也是 JedisPool ,使用完毕的 Jedis 也需要通过 close() 方法将其返回给 连接池

public class JedisSentinelPoolTest {

	private JedisSentinelPool jedisPool;

    {
        Set<String> sentinel =  new HashSet<>();
        sentinel.add("192.168.216.128:26380");
        sentinel.add("192.168.216.128:26381");
        sentinel.add("192.168.216.128:26382");

        jedisPool = new JedisSentinelPool("mymaster", sentinel);
    }
    // value为String的情况
    @Test
    public void test01() {
        try(Jedis jedis =  jedisPool.getResource()) {
            jedis.set("name", "张三");
            jedis.mset("age", "23", "depart", "市场部");

            System.out.println("name = " + jedis.get("name"));
            System.out.println("age = " + jedis.get("age"));
            System.out.println("depart = " + jedis.get("depart"));
        }
    }
}

在这里插入图片描述
在这里插入图片描述

7.1.7 连接分布式系统

    对于 Redis 的分布式系统的连接,直接使用 JedisCluster 即可。其底层采用的也是 Jedis连接池技术。每次使用完毕后,无需显式关闭,其会自动关闭

    对于 JedisCluster 常用的 构造器 有两个。

  • 一个是 只需一个集群节点构造器,这个节点可以是集群中的任意节点,只要连接上了该节点,就连接上了整个集群。但该构造器存在一个风险:其指定的这个节点在连接之前恰好宕机,那么该客户端将无法连接上集群
  • 所以,推荐使用第二个 构造器,即将集群中所有节点全部罗列出来。这样就会避免这种风险了 。
public class JedisClusterTest{
	private JedisCluster jedisCluster;
	{
		// 连接CLuster中的任意主机
		// HostAndPort node = new HostAndPort("redis", 6380);
		// jedisCluster = new JedisCluster(node);
		
		//连接整个CLuster
		HashSet<HostAndPort> nodes = new HashSet<>();
		nodes.add(new HostAndPort("redis", 6380));
		nodes.add(new HostAndPort("redis", 6381));
		nodes.add(new HostAndPort("redis", 6382));
		nodes.add(new HostAndPort("redis", 6383));
		nodes.add(new HostAndPort("redis", 6384));
		nodes.add(new HostAndPort("redis", 6385));
		jedisCluster = new JedisCluster(nodes);
	}
	
	// value为String的情况
	@Test
	public void test01() {
		jedisCluster,set("name", "张三");
		// 会出现跨槽,报错
		// jedisClustermset("age", "23", "depart","行政部");
		System.out.println("name = " + jedisCluster.get("name"));
	}
}

在这里插入图片描述

7.1.8 操作事务

    对于 Redis 事务 的操作, Jedis 提供了 multi()watch()unwatch() 方法来对应 Redis 中的 multiwatchunwatch 命令。 Jedis 的 multi() 方法返回一个 Transaction 对象,其 exec()discard() 方法用于 执行和取消事务的执行

⭐️(1) 抛出 Java 异常

public class JedisTxTest {

    private JedisPool jedisPool = new JedisPool("192.168.216.128", 6379);

    // value为String的情况
    @Test
    public void test01() {
        try(Jedis jedis =  jedisPool.getResource()) {
            jedis.set("name", "张三");
            jedis.mset("age", "23");

            Transaction multi = jedis.multi();
            try{
                multi.set("name", "李四");
                // 构造一个 Java 异常
                int i = 3 / 0;
                multi.set("age", "24");
                multi.exec();
            }catch (Exception e){
                // 一旦发生异常,全部回滚
                multi.discard();
            }finally {
                System.out.println("name = " + jedis.get("name"));
                System.out.println("age = " + jedis.get("age"));
            }
        }
    }
}

在这里插入图片描述

    其输出结果为全部回滚的结果

⭐️(2) 让 Redis 异常

@Test
public void test02() {
    try(Jedis jedis = jedisPool.getResource()) {
        jedis.set("name", "张三");
        jedis.mset("age", "23");

        Transaction tx = jedis.multi();
        try {
            tx.set("name", "李四");
            // 构造出一个Redis异常
            tx.incr("name");
            tx.set("age", "24");
            tx.exec();
        } catch (Exception e) {
            // 发生异常,全部回滚
            tx.discard();
        } finally {
            System.out.println("name = " + jedis.get("name"));
            System.out.println("age = " + jedis.get("age"));
        }
    }
}

在这里插入图片描述

    其输出结果为修改过的值。说明 Redis 运行时 抛出的异常不会被 Java 代码 捕获到,其 不会影响 Java 代码的执行。

⭐️(3) watch()

@Test
public void test03() {
    try(Jedis jedis = jedisPool.getResource()) {
        jedis.mset("age", "23");
        System.out.println("age增一前的值:" + jedis.get("age"));

        jedis.watch("age");
        Transaction tx = jedis.multi();
        try {
            tx.incr("age");
            tx.exec();
        } catch (Exception e) {
            tx.discard();
        } finally {
            System.out.println("age增一后的值:" + jedis.get("age"));
        }
    }
}

在这里插入图片描述

7.2 金融产品交易平台

7.2.1 Spring Boot 整合 Redis

7.2.2 Redis 操作模板

    Spring Boot 中可以直接使用 Jedis 实现对 Redis 的操作,但一般不这样用,而是使用 Redis 操作模板 RedisTemplate 类的实例来操作 Redis

    RedisTemplate 类是一个对 Redis 进行操作的模板类。该模板类中具有很多方法,这些方法很多与 Redis 操作命令同名或类似。例如, delete()keys()scan(),还有事务相关的 multi()exec()discard()watch() 等。当然还有获取对各种 Value 类型进行操作的操作实例的两类方法 boundXxxOps(k)opsForXxx()

7.2.3 需求

    下面通过一个例子来说明 Spring Boot 是如何与 Redis 进行 整合 的。

    对于一个资深成熟的金融产品交易平台,其用户端首页一般会展示其最新金融产品列表同时还为用户提供了产品查询功能。另外,为了显示平台的实力与信誉,在平台首页非常显眼的位置还会展示平台已完成的总交易额注册用户数量。对于管理端,管理员可通过管理页面修改产品上架新产品下架老产品

    为了方便了解 RedisSpring Boot 的整合流程,这里对系统进行了简化:

  • 用户端 首页提供根据金融产品名称的查询,显眼位置仅展示交易总额。
  • 管理端 仅实现上架新产品功能

7.2.4 创建 SSM 工程

⭐️(1) 创建工程

    定义一个 Spring Boot 工程,并命名为 ssm

⭐️(2) 定义 pom 文件

    在 pom 文件中需要导入 MySQL 驱动Druid 等大量依赖。 POM 文件中的重要内容如下:

	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/webapp</directory>
                <targetPath>META-INF/resources</targetPath>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
    </build>

⭐️(3) 修改主配置文件

    在主配置文件中配置 MyBatisSpring日志等配置:

⭐️(4) 实体类 Product

平台交易总额,即“产品募集结束日期”小于“当前查询日期”的“产品募集总额”之和。

⭐️(5) 创建数据库表

    在 test 数据库中创建一个名称为 product 的表。创建的 sql 文件如下,直接运行该文件即可。

⭐️(6) 定义 index.jsp

    在 src/main 下创建 webap 目录,用于存放 jsp 文件。这就是一个普通的目录,无需执行 Mark Directory As 。在 webapp 目录中创建一个 index.jsp 文件。

⭐️(7) 定义 manager.jsp

    在 webapp 目录下再创建一个 jsp 子目录,在其中定义 manager.jsp

⭐️(8) 定义 result.jsp

    在 webapp/jsp 中定义 result.jsp

⭐️(9) ProductController 类

A、 indexHandle()

B、 registerHandle()

C、 listHandle()

⭐️(10) ProductService 接口

⭐️(11) ProductServiceImpl 类

A、 saveProduct()

B、 三个 find 方法

⭐️(12) ProductDao 接口

⭐️(13) 映射文件

⭐️(14) Application 启动类

7.2.5 创建 SSRM 工程

7.3 高并发问题

    Redis做缓存虽减轻了 DBMS 的压力,减小了 RT ,但在 高并发 情况下也是可能会出现各种问题的。

7.3.1 缓存穿透

    当用户访问的 数据 既不在缓存 也不在数据库中 时,就会导致每个用户查询都会 “穿透缓存直抵数据库。这种情况就称为缓存穿透。当高并发的访问请求到达时,缓存穿透不仅增加了响应时间,而且还会引发对 DBMS 的高并发查询,这种 高并发查询 很可能会导致DBMS 的崩溃

    缓存穿透产生的主要原因有两个:一是在数据库中 没有 相应的查询结果,二是查询结果为 时,不对查询结果进行缓存。所以,针对以上两点,解决方案也有两个:

  • 非法请求 进行 限制
  • 结果为空 的查询给出 默认值
7.3.2 缓存击穿

    对于 某一个缓存 ,在高并发情况下若其访问量特别巨大,当 该缓存的有效时限到达时,可能会出现大量的访问都要重建该缓存,即这些访问请求发现缓存中没有该数据,则立即到 DBMS 中进行查询,那么这就有可能会引发对 DBMS高并发查询,从而接导致 DBMS 的崩溃。这种情况称为缓存击穿,而该缓存数据称为 热点数据

    对于缓存击穿 的解决方案,较典型的是使用 “双重检测锁 ” 机制。

7.3.3 缓存雪崩

    对于缓存中的数据,很多都是有过期时间的。若 大量缓存过期时间在同一很短的时间段内几乎同时到达,那么在高并发访问场景下就可能会引发对 DBMS 的高并发查询,而这将可能直接导致 DBMS 的崩溃。这种情况称为 缓存雪崩

    对于缓存雪崩没有很直接的解决方案,最好的解决方案就是 预防 ,即提前规划好缓存的过期时间。

  • 要么就是让缓存 永久有效,当 DB 中数据发生变化时清除相应的缓存。
  • 如果 DBMS 采用的是 分布式部署,则将热点数据 均匀分布在不同数据库节点中,将可能到来的访问负载均衡开来。
7.3.4 数据库缓存双写不一致

    以上三种情况都是针对 高并发 场景中可能会出现的问题,而数据库缓存双写不一致问题,则是在 高并发 场景下可能会出现的问题。

    对于数据库缓存 双写不一致 问题,以下两种场景下均有可能会发生:

⭐️(1) “修改 DB 更新缓存” 场景

    对于具有缓存 warmup 功能的系统, DBMS 中常用数据的变更,都会引发缓存中相关数据的更新。在 高并发 请求场景下,若多个请求要对 DBMS 中同一个数据进行修改,修改后还需要更新缓存中相关数据,那么就有可能会出现 缓存数据库中 数据 不一致的情况。

在这里插入图片描述

⭐️(2) “修改 DB 删除缓存” 场景

    在很多系统中是没有缓存 warmup 功能的,为了保持缓存与数据库数据的一致性,一般都是在对数据库执行了写操作后,就会 删除 相应缓存

    在 高并发读写 请求场景下,若这些请求对 DBMS 中同一个数据的操作既包含也包含,且修改后还要删除缓存中相关数据,那么就有可能会出现缓存与数据库中数据不一致的情况。

在这里插入图片描述

⭐️(3) 解决方案:延迟双删

    延迟双删 方案是专门针对于“ 修改DB 删除缓存 ” 场景的解决方案。但该方案并不能彻底解决数据不一致的状况,其只可能降低发生数据不一致的概率。

    延迟双删方案是指,在写操作完毕后会立即执行一次缓存的删除操作,然后再停上一段时间(一般为几秒)后再进行一次删除。而两次删除中间的间隔时长,要大于一次 缓存写操作时长

在这里插入图片描述

⭐️(4) 解决方案:队列

    以上两种场景中,只所以会出现 数据库缓存数据不一致,主要是因为 对请求的处理出现了并行。只要将请求写入到一个统一的队列,只有处理完一个请求后才可处理下一个请求,即使系统对用户请求的处理 串行化,就可以完全解决数据不一致的问题。

⭐️(5) 解决方案:分布式锁

    使用队列的串行化虽然可以解决数据库与缓存中数据不一致,但系统 失去了并发性,降低了性能。使用 分布式锁 可以在不影响并发性的前提下,协调各处理线程间的关系,使数据
库与缓存中的数据达成一致性。

    只需要对数据库中的这个共享数据的访问通过 分布式锁 来协调对其的操作访问即可。



注:仅供学习参考,如有不足,欢迎指正!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Power Automate删除SharePoint Online或OneDrive for Business文件版本历史

SharePoint Online和OneDrive for Business支持版本控制&#xff0c;可以保留文件的版本历史&#xff0c;方便用户随时查看和恢复以前的版本。但该功能也会占用大量SharePoint Online或OneDrive for Business存储空间。官方删除版本历史的方法无法批量操作&#xff0c;故今天提…

122基于matlab的CSO-SVM,BA-SVM模式识别模型

基于matlab的CSO-SVM&#xff0c;BA-SVM模式识别模型。优化SVM的两个参数晚上最佳参数确定。输出分类识别结果和准确率。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 122鸡群优化算法蝙蝠优化算法 (xiaohongshu.com)

ASP.NET Core基础之图片文件(一)-WebApi图片文件上传到文件夹

阅读本文你的收获&#xff1a; 了解WebApi项目保存上传图片的三种方式学习在WebApi项目中如何上传图片到指定文件夹中 在ASP.NET Core基础之图片文件(一)-WebApi访问静态图片文章中&#xff0c;学习了如何获取WebApi中的静态图片&#xff0c;本文继续分享如何上传图片。 那么…

Linux 如何 kill 指定的 python 进程

文章目录 写在前面一、显示python相关的进程二、找到自己想要 kill 的进程&#xff0c;执行下述指令 写在前面 自己的系统是 Ubuntu 20.04 一、显示python相关的进程 ps -ef | grep python显示结果如下 其中&#xff0c;第二列分别是各个进程的 PID 号。 二、找到自己想要…

芯课堂 | MCU之TIMER精准延时

引言 华芯微特公司SWM系列单片机提供的TIMER个数和功能有些微差别&#xff0c;为了让您更加简单的使用这一功能&#xff0c;下面小编将以SWM190为例&#xff0c;给大家展示如何使用SWM系列产品的TIMER功能。 TIMER精准延时 一、TIMER简介 TIMER是一种定时器工具&#xff0c;…

数字信号处理期末复习——基础知识汇总(三)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

(vue)增加行,对应行删除

(vue)增加行&#xff0c;对应行删除 效果&#xff1a; 代码&#xff1a; <div v-for"(ele,i) of algorithmList" :key"i"><el-form-item label"模型类型"><el-selectv-model"ele.algorithmId"placeholder"选择模…

技术旅程分享:收获与成长的探索

2023年对我而言是充满挑战和机遇的一年&#xff0c;我在这段时间里积累了丰富的技术经验和个人成长。通过不懈努力和持续学习&#xff0c;我在技术领域迈出了一系列坚实的步伐。在这篇文章中&#xff0c;我将分享我在这段时间中的收获和技术成长经历&#xff0c;与CSDN的朋友们…

基于Vue的宿舍管理系统

基于Vue的宿舍管理系统资源-CSDN文库 基于 Koa 以及 VueJS 的宿舍管理系统。 新增功能&#xff1a; 【楼层管理】添加『入住人员信息』模块&#xff0c;显示入住学生、性别、院系、专业的人数&#xff0c;可用饼图表示【用户信息】学生用户添加性别、院系、专业字段【楼层管理…

【Vue2+3入门到实战】(21)认识Vue3、使用create-vue搭建Vue3项目、熟悉项目和关键文件

目录 一、认识Vue31. Vue2 选项式 API vs Vue3 组合式API2. Vue3的优势 二、 使用create-vue搭建Vue3项目1. 认识create-vue2. 使用create-vue创建项目 三、 熟悉项目和关键文件四、总结 一、认识Vue3 1. Vue2 选项式 API vs Vue3 组合式API <script> export default {…

YOLOv8改进 | 主干篇 | CSWinTransformer交叉形窗口网络

一、本文介绍 本文给大家带来的改进机制是CSWin Transformer,其基于Transformer架构,创新性地引入了交叉形窗口自注意力机制,用于有效地并行处理图像的水平和垂直条带,形成交叉形窗口以提高计算效率。它还提出了局部增强位置编码(LePE),更好地处理局部位置信息,我将其…

Kubernetes之Ingress详解

目录 IngressIngress配置配置写法转发到单个后端服务不同的URL路径被转发到不同的服务上不同的域名转发到不同的服务上不使用域名的转发规则 Ingress Ingress 是 Kubernetes 中的一种 API 对象&#xff0c;用于管理和配置集群中的 HTTP 和 HTTPS 服务路由。 Ingress 可以在 K…

Termius for Mac/Win:一款功能强大的终端模拟器、SSH 和 SFTP 客户端软件

随着远程工作和云技术的普及&#xff0c;对于高效安全的远程访问和管理服务器变得至关重要。Termius&#xff0c;一款强大且易用的终端模拟器、SSH 和 SFTP 客户端软件&#xff0c;正是满足这一需求的理想选择。 Termius 提供了一站式的解决方案&#xff0c;允许用户通过单一平…

webpack知识点总结(高级应用篇)

除开公共基础配置之外&#xff0c;我们意识到两点: 1. 开发环境(modedevelopment),追求强大的开发功能和效率&#xff0c;配置各种方便开 发的功能;2. 生产环境(modeproduction),追求更小更轻量的bundle(即打包产物); 而所谓高级应用&#xff0c;实际上就是进行 Webpack 优化…

清风数学建模笔记-时间序列分析

内容&#xff1a;时间预测分析 一.时间序列 1.时点时间序列 2.时期时间序列&#xff1a;可相加 二.时间趋势分解 1.季节趋势 拓展&#xff1a;百度指数&#xff1a; 2.循环变动趋势&#xff08;和季节很像但是是以年为单位&#xff09; 3.不规则变动趋势&#xff08;像扰…

微信小程序封装vant 下拉框select 单选组件

先上效果图&#xff1a; 主要是用vant 小程序组件封装的&#xff1a;vant 小程序ui网址&#xff1a;vant-weapp 主要代码如下: 先封装子组件&#xff1a; select-popup 放在 components 文件夹里面 select-popup.wxml: <!--pages/select-popup/select-popup.wxml--> &…

(JAVA)-反射

什么是反射&#xff1f; 反射允许对成员变量&#xff0c;成员方法和构造方法的信息进行编程访问。 说简单点就是反射能将类里面的构造方法&#xff0c;成员变量,修饰符,返回值&#xff0c;注解&#xff0c;类型&#xff0c;甚至异常等类里面的所有东西都能够获取出来。 关于C…

Canvas保姆级教程----深入解析HTML5 Canvas工作原理和常用方法

&#x1f4e2; 鸿蒙专栏&#xff1a;想学鸿蒙的&#xff0c;冲 &#x1f4e2; C语言专栏&#xff1a;想学C语言的&#xff0c;冲 &#x1f4e2; VUE专栏&#xff1a;想学VUE的&#xff0c;冲这里 &#x1f4e2; CSS专栏&#xff1a;想学CSS的&#xff0c;冲这里 &#x1f4…

8086CPU的寻址方式(7种)

基本概念 立即操作数&#xff1a;操作数包含在指令中寄存器操作数&#xff1a;操作数包含在CPU的某个内部寄存器中存储器操作数&#xff1a;约定操作数事先存放在存储器中存放数据的某个单元基本格式 MOV xx,yy xx&#xff1a;目的操作数字段 yy&#xff1a;源操作数字段 EA&a…

英飞凌AURIX 2G TC3xx新一代芯片架构系列介绍-概论

英飞凌AURIX 2G TC3xx新一代芯片架构系列介绍-概论