当前位置: 首页 > news >正文

Java技术栈 —— Redis的雪崩、穿透与击穿

Java技术栈 —— Redis的雪崩、穿透与击穿

  • 〇、实验的先导条件(Nginx+Jmeter)
  • 一、Redis缓存雪崩、缓存穿透、缓存击穿
    • 1.1 雪崩
    • 1.2 穿透
    • 1.3 击穿
  • 二、Redis应用场景——高并发
    • 2.1 单机部署的高并发问题与解决(JVM级别锁)
    • 2.2 集群部署的高并发问题与解决(分布式锁)
      • 2.2.1 代码1(存在非原子操作与释放问题)
      • 2.2.2 代码2(finally块中,存在释放其它线程锁的可能性)
      • 2.2.3 代码3(redisson)
        • 2.2.3.1 Java中嵌入Lua脚本
      • 2.2.4 对代码3的性能优化、redis主从架构锁失效问题的解决方案
        • 2.2.4.1 性能优化的解决(分段锁,重要)
        • 2.2.4.2 主从架构锁失效问题的解决
            • 2.2.4.2.1 zookeeper
            • 2.2.4.2.2 redis的RedLock
  • 三、Redis与数据库的数据一致性

〇、实验的先导条件(Nginx+Jmeter)

首先你需要掌握Nginx负载均衡与Jmeter压测工具,搭建过程与使用方式,见参考文章。

参考文章或视频链接
[1] 《Java技术栈 —— Nginx的使用》
[2] 2 ways to install Apache JMeter on Ubuntu 22.04 LTS Linux

一、Redis缓存雪崩、缓存穿透、缓存击穿

关于雪崩、穿透与击穿的原理,可以先看本节的参考文章[1],代码以后再写到文章中。

1.1 雪崩

1.2 穿透

1.3 击穿

一、参考文章或视频链接
[1] 【什么是Redis缓存雪崩、穿透、击穿,十分钟给你讲的明明白白】- bilibili

二、Redis应用场景——高并发

高并发导致的问题,本质就是资源争抢。 在操作系统中,这类问题的雏形有哲学家用餐问题、进程争夺计算资源,相关解决机制有信号量机制,所以道理都是相通的,高并发在计算机领域并不是什么新鲜事,只是落地到应用场景,会有一些其它考量。就像古代兵符印信,或是倚天屠龙记中说的“武林至尊,宝刀屠龙,号令天下,莫敢不从!倚天不出,谁与争锋?”,听谁的问题的解决方法啊,就是象征物在谁手上就听谁的,包括抢职位争权力,也可以理解为一种并发,谁坐到了那个位置,才有号令的权力,但是权力是致命毒药,要小心哦!

首先导入jedis依赖,从而可以用java程序包操纵redis,以下是完整依赖。

	<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency><!--实现分布式锁redisson--><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.6.5</version></dependency>
<!-- 也可以手动引入Jedis,不用SpringBoot提供的spring-boot-starter-data-redis--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>5.1.0</version></dependency><!--如果你导入了下面的SpringBoot父依赖,会自带Jedis,不过版本不一定最新而已,并且有些-->
<!--	<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.1</version><relativePath/> </parent>用SpringBoot提供的Jedis版本<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency> -->

然后,我们开始复现高并发问题。首先是假设你已经搭建了一个简单的SpringBoot项目架构,并且相关的Nginx配置也已配置好,可以看 参考文章[5] 《Java技术栈 —— Nginx的使用》第3.1节,那正是我为本文而写,项目demo搭好了,port号也初步定为9998

二、参考文章或视频链接
[1] Java guide(Jedis) - Redis Offical Website
[2] Intro to Jedis – the Java Redis Client Library
[3] Redis可视化工具 RedisInsight | The best Redis GUI
[4] 示例代码来源,图灵诸葛老师,讲的确实很好: 【这可能是目前讲的最好的Redis高并发架构教程,堪称Redis架构实战的天花板!】
[5] 《Java技术栈 —— Nginx的使用》

2.1 单机部署的高并发问题与解决(JVM级别锁)

(1)先在redis中设置缓存好一个键值对,键的名字为store,这是我们要高并发的对象。

$ redis-cli
127.0.0.1:6379>	SETNX store 2000
127.0.0.1:6379>	get store
"2000"

(2)写一段操作redis获取store值的代码,完整项目代码最后会附上开源地址。

@RestController
public class demoController {public static int count = 0;@RequestMapping("deduct_stock_then_get_stock")public Integer deductStock(){Jedis jedis = new Jedis("127.0.0.1", 6379);int currentStock = Integer.parseInt(jedis.get("stock"));if (currentStock > 0){currentStock--;jedis.set("stock", String.valueOf(currentStock));System.out.println("扣减成功,剩余库存"+currentStock);}else{System.out.println("扣减失败,库存不足");}return currentStock;}
}

启动项目并访问http://127.0.0.1:9998/deduct_stock_then_get_stock,让我们先看看效果,慢慢迭代,好的,现在浏览器上已经返回了当前库存数量,显示是199不要在意,这个数字随时可以在redis中修改。

然后我们用Jmeter,模拟多个用户同时访问 http://127.0.0.1:9998/deduct_stock_then_get_stock,上面这段Java代码会出什么问题呢?简单来说,就是会出现超卖问题。按下面的过程配置,并点击绿色的启动箭头在这里插入图片描述,就开启了压测。

在这里插入图片描述在这里插入图片描述在这里插入图片描述
这是控制台输出的结果,果然,出现了超卖问题,这说明会有多个用户都看到了相同的1999库存,很明显是有问题的,这是因为多个用户同时进入了相同段代码的执行过程,并且都拿到了一个currentStock变量作为副本,而这个变量在获取的时候出现了值相同的情况。

@RestController
public class demoController { //方法(2)以函数为单位上锁,写成 public synchronized Integer deductStock(){@RequestMapping("deduct_stock_then_get_stock")public Integer deductStock(){Jedis jedis = new Jedis("127.0.0.1", 6379);synchronized (this){ //方法(1)以对象为单位上锁int currentStock = Integer.parseInt(jedis.get("stock")); //上一段未加synchronized的代码,问题出在这里,都获取到了一样的值,那么再进行currentStock--,就是1999了if (currentStock > 0){currentStock--;jedis.set("stock", String.valueOf(currentStock));System.out.println("扣减成功,剩余库存"+currentStock);}else{System.out.println("扣减失败,库存不足");}return currentStock;}}}

只加了一个锁,问题解决,那么到目前为止,单机部署的高并发问题,可以算解决了,如果集群部署的话,上面这段代码还有用吗?

2.2 集群部署的高并发问题与解决(分布式锁)

根据参考视频[4]所说,上面的代码也只是解决了单机部署下的高并发问题,如果是集群部署,启动了多个服务分别部署在不同机器上呢?这个时候Nginx会分发请求到不同服务实例上,还会出现上面的超卖现象吗?答案是会的,这相当于线程A在服务A上执行扣库存,线程B在服务B上执行扣库存,这两个线程压根不归同一个JVM虚拟机进程管,是没办法用上面的加synchronized关键字去限制的,具体可以看视频讲解。但是,只要思想不滑坡,办法总比困难多,请看。PS:你能想象,其实12306是全世界最能抗高并发的软件吗?总有些东西在微不足道的角落里熠熠生辉,独自发热。
还是刚刚那段,在单机部署上解决了高并发问题的代码,我们来多启动一个服务,只是端口不同。

由于在参考文章[5]中,我已经配置了Nginx,所以我们的Jmeter测试地址,应该改为http://127.0.0.1:8011/deduct_stock_then_get_stock,看下面的两张截图,和视频[5]里说的一样,确实在集群部署时会出现超卖问题。

下面是加上分布式锁的解决方法, 但是仍然存在问题。

2.2.1 代码1(存在非原子操作与释放问题)

@RestController
public class demoController {@RequestMapping("deduct_stock_then_get_stock")public Integer deductStock(){String lockKey = "product_100";Jedis jedis = new Jedis("127.0.0.1", 6379);long result = jedis.setnx(lockKey,"xxx"); // 获取分布式锁if(result == 0){System.out.println("争抢分布式锁失败"); /*注意,这里实际使用会有问题,不应该return,只是作为示例争抢分布式锁失败的话也应该程门立雪,三顾茅庐,不可半途而返,半途而返会导致许多业务请求被扼杀*/ return 500;                          }//*****重要思维*****//业务逻辑,可能出异常,导致分布式锁无法释放,永远要考虑系统的业务逻辑被某种不可抗力因素停止,不管是运维还是什么,程序要具备健壮性。int currentStock = Integer.parseInt(jedis.get("stock"));if (currentStock > 0) {currentStock--;jedis.set("stock", String.valueOf(currentStock));System.out.println("扣减成功,剩余库存" + currentStock);} else {System.out.println("扣减失败,库存不足");}jedis.del(lockKey);  //释放分布式锁return currentStock;}}

2.2.2 代码2(finally块中,存在释放其它线程锁的可能性)

下面的代码对上面的代码做了两处改进:
(1)将获取与设置超时时间这两步,组合成原子操作,不可分离。
(2)增加clientID,保证释放的是自己加的锁,但在释放仍旧可能存在问题,视频中提到用redisson进行解决,见 redisson - github wiki,redisson与jedis区别在于,jedis只是提供一些原生命令的实现,redisson可以提供分布式锁的实现能力。

@RequestMapping("deduct_stock_then_get_stock")
public Integer deductStock(){ //集群版//(1)获得分布式锁String lockKey = "product_100";Jedis jedis = new Jedis("127.0.0.1", 6379);String clientID = UUID.randomUUID().toString(); //唯一ID,加锁人的身份//        String result = jedis.setex(lockKey, 10, clientID); //该命令是原子命令,将获取与设置超时时间这两步,组合成原子操作,不可分离,但还是存在问题,如业务逻辑执行较慢,锁已经超时释放了业务逻辑还没执行完,又导致了并发Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, clientID, 10, TimeUnit.SECONDS);  //该命令是原子命令,将获取与设置超时时间这两步,组合成原子操作,不可分离,但还是存在问题,如业务逻辑执行较慢,锁已经超时释放了业务逻辑还没执行完,又导致了并发stringRedisTemplate.opsForValue().get(lockKey);if(result == Boolean.FALSE){System.out.println("争抢分布式锁失败");  // 分布式锁争抢失败应该等待,而不应该直接returnreturn 500;}try{//*****重要思维*****//(2)执行业务逻辑,可能出异常,导致分布式锁无法释放,永远要考虑系统的业务逻辑被某种不可抗力因素停止,不管是运维还是什么,要具备健壮性。//此处可能存在的异常有:// (2.1)业务逻辑执行失败,但finally可以正常释放分布式锁// (2.2)应用被重启,连finally都无法执行,那么就需要令分布式锁自动过期int currentStock = Integer.parseInt(jedis.get("stock"));if (currentStock > 0) {currentStock--;jedis.set("stock", String.valueOf(currentStock));System.out.println("扣减成功,剩余库存" + currentStock);} else {System.out.println("扣减失败,库存不足");}return currentStock;}finally{//(3)出异常时释放分布式锁,这里释放分布式锁可能存在问题if (clientID.equals(jedis.get(lockKey))){//自己加的锁才能释放,中间还可能存在执行时间的间隔,开一个分线程,将分布式锁加时,检测这把分布式锁还是否加载在该主线程中,加时到直到业务逻辑执行完成为止jedis.del(lockKey);}}}

2.2.3 代码3(redisson)

@RequestMapping("deduct_stock_then_get_stock_cluster_redisson")
public Integer deductStock3(){ //集群+redisson版//(1)获得分布式锁String lockKey = "product_100";Jedis jedis = new Jedis("127.0.0.1", 6379);RLock redissonLock = redisson.getLock(lockKey); //获取RLock对象try{redissonLock.lock(); //(2)上锁,底层调用redis命令时用到了lua脚本//(3)业务逻辑int currentStock = Integer.parseInt(jedis.get("stock"));if (currentStock > 0) {currentStock--;jedis.set("stock", String.valueOf(currentStock));System.out.println("扣减成功,剩余库存" + currentStock);} else {System.out.println("扣减失败,库存不足");}return currentStock;}finally{//(4)释放锁redissonLock.unlock();}
}

redisson是一种Redis Java client,上述redisson的使用方法,也是大厂在生产环境会用到的,但上面的代码还有两个问题:
(1)性能问题,虽然没有超卖,但会导致系统性能问题,需要开始性能优化。
(2)redis主从架构下,锁失效问题。比如Master同步给Slave分布式锁时,Master正好挂掉,然后重新选举的Master正好没有同步到这把锁,就失效了。

2.2.3 参考文章或视频链接
[1] 1. Overview of Redisson - GitHub
2.2.3.1 Java中嵌入Lua脚本

什么是Lua脚本?我第一次听说Lua,是在敖丙解说B站出事那次,最后定位到一段Lua写的gcd()代码,久闻大名却未上手实操过。请看本节参考文章[1]。

2.2.3.1 参考文章或视频链接
[1] Lua:about - Offical Website

2.2.4 对代码3的性能优化、redis主从架构锁失效问题的解决方案

2.2.4.1 性能优化的解决(分段锁,重要)

先了解下并发编程集合类ConcurrentHashMap,这是一个高并发的Java集合类且线程安全,其保证线程安全的原理是,使用分段锁。受此启发,性能优化也可以用分段加锁,每个线程去不同的段位请求锁即可。

2.2.4.1 参考文章或视频链接
[1] 《详解ConcurrentHashMap》- CSDN
2.2.4.2 主从架构锁失效问题的解决
  • Zookeeper集群是CP架构。
  • Redis单机是CP架构,Redis集群是AP架构。[5]

CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

CAP理论

2.2.4.2 参考文章或视频链接
[1] Redis persistence and CAP theorem-From Zero to Hero -part II
[2] 《架构设计之「 CAP 定理 」》- CSDN
[3] 《CAP定理一文带你速解(通俗易懂,图文并茂)》- CSDN
推荐优先阅读:[4] 《NoSQL 简介》- 菜鸟教程
[5] 《redis是CA还是CP呢》- 腾讯云
2.2.4.2.1 zookeeper

使用zookeeper,zookeeper解决主从架构锁失效问题更合适,但会牺牲一点性能。

2.2.4.2.1 参考文章或视频链接
[1] What is Apache ZooKeeper?
[2] Welcome to Apache ZooKeeper
[3] 《2.0 Zookeeper 安装配置》- 菜鸟
[4] 《zookeeper快速入门一:zookeeper安装与启动》
2.2.4.2.2 redis的RedLock

要超过半数redis节点加锁成功才算成功,这样的原理又回到了zookeeper,还是会损失加锁的性能,所以RedLock实现的是否完善依旧存在争议。
在这里插入图片描述

三、Redis与数据库的数据一致性

(1)要保证的是数据的最终一致性,而不是强一致性,若要保证数据强一致性会损失性能,这违背了使用Redis的初衷。
(2)删除Redis缓存,而不是更新Redis缓存。
(3)先更新数据库数据。

三、 参考文章或视频链接
[1] 《字节二面:redis如何保证缓存和数据库的一致性》

相关文章:

Java技术栈 —— Redis的雪崩、穿透与击穿

Java技术栈 —— Redis的雪崩、穿透与击穿 〇、实验的先导条件&#xff08;NginxJmeter&#xff09;一、Redis缓存雪崩、缓存穿透、缓存击穿1.1 雪崩1.2 穿透1.3 击穿 二、Redis应用场景——高并发2.1 单机部署的高并发问题与解决&#xff08;JVM级别锁&#xff09;2.2 集群部署…...

Scala知识点——App类

我们在代码中一般程序都是是通过main方法进入。但是在scala中提供了一个App类&#xff0c;通过继承可以实现不用显式的调用main方法就能运行。 App类中实现了main方法&#xff1a;...

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

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

案例088:基于微信小程序的校车购票平台设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…...

pytorch集智-1安装与简单使用

1 安装 1.1 简介 pytorch可用gpu加速&#xff0c;也可以不加速。gpu加速是通过cuda来实现&#xff0c;cuda是nvidia推出的一款运算平台&#xff0c;它可以利用gpu提升运算性能。 所以如果要装带加速的pytorch&#xff0c;需要先装cuda&#xff0c;再装pytorch&#xff0c;如…...

『番外篇六』SwiftUI 取得任意视图全局位置的三种方法

概览 在 SwiftUI 开发中,利用描述性代码我们可以很轻松的构建各种丰富多彩的视图。我们可以设置它们的大小、位置、颜色并应用不计其数的修改器。 但是,小伙伴们是否想过在 SwiftUI 中如何获取一个视图的全局位置坐标呢? 在本篇博文中,您将学到如下内容: 概览1. SwiftU…...

Ribbon相关面试及答案(2024)

1、Ribbon是什么&#xff0c;它在微服务架构中扮演什么角色&#xff1f; Ribbon是一个客户端负载均衡器&#xff0c;它在微服务架构中扮演着关键性的角色。Ribbon的设计理念是在客户端进行服务发现和负载均衡&#xff0c;这种方式不同于传统的通过中心化的负载均衡器&#xff…...

【Mybatis】深入学习MyBatis:CRUD操作与动态SQL实战指南

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; Mybatis ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 一基本用法 1 CRUD操作 1. 增加&#xff08;Create&#xff09; 2. 查询&#xff08;Read&#xff09; 3. 更新&#x…...

前端uniapp的tab选项卡for循环切换、开通VIP实战案例【带源码/最新】

目录 效果图图1图2 源码最后 这个案例是uniapp&#xff0c;同样也适用Vue项目&#xff0c;语法一样for循环&#xff0c;点击切换 效果图 图1 图2 源码 直接代码复制查看效果 <template><view class"my-helper-service-pass"><view class"tab…...

【我的RUST库】get_local_info

get_local_info是一个获取linux本地信息的Rust三方库&#xff0c;其目标是降低获取本地linux系统信息的难度。支持银河麒麟10、UOS、鸿蒙等国产系统 项目维护&#xff1a;长期 当前版本0.1.4&#xff0c;已有功能&#xff1a; 1.获取活动网卡信息&#xff1a;网卡&#xff0…...

【JUC】Synchronized及JVM底层原理

Synchronized使用方式 Synchronized有三种应用方式 作用于实例方法&#xff0c;当前示实例加锁进入同步代码前要获得当前实例的锁&#xff0c;即synchronized普通同步方法&#xff0c;调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置。 如果设置了&#xff0c;执行…...

用户管理第2节课--idea 2023.2 后端--实现基本数据库操作(操作user表) -- 自动生成 --【本人】

一、插件安装 1.1 搜索插件 mybatis 安装 1.2 接受安装 1.3 再次进入&#xff0c;说明安装好了 1.4 与鱼皮不同点 1&#xff09;mybatis 版本不一致 鱼皮&#xff1a; 本人&#xff1a; 2&#xff09;鱼皮需重启安装 本人不需要 1.5 【需完成 三、步骤&#xff0c;再来看】 …...

深入了解隧道代理HTTP的协议与技术细节

隧道代理HTTP&#xff0c;作为一种网络通信的桥梁技术&#xff0c;其背后的协议与技术细节承载着网络世界的无尽奥秘。对于技术人员而言&#xff0c;深入了解这些细节&#xff0c;不仅有助于优化网络性能&#xff0c;还能为网络安全提供坚实的保障。 一、隧道代理HTTP的协议基…...

系统运维-Apache服务的基础安装与使用

Apache&#xff1a;WEB服务器的软件 Apache HTTP是一个模块化的服务器&#xff0c;源于NCSAhttpd服务器&#xff0c;经过多次修改&#xff0c;成为世界使用排名第一的WEB服务器软件。 目录 HTTP HTTPS HTTP 首先安装apache yum install httpd* -y #install http 要有网站首…...

Android 相机库CameraView源码解析 (四) : 带滤镜预览

1. 前言 这段时间&#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位&#xff0c;在项目前期&#xff0c;的确为我们节省了不少时间。 但随着项目持续深入&#xff0c;对于CameraView的使用进入深水区&#xff0c;逐…...

蜥蜴目标检测数据集VOC格式1400张

蜥蜴&#xff0c;一种爬行动物&#xff0c;以其独特的形态和习性&#xff0c;成为了人们关注的焦点。 蜥蜴的外观多样&#xff0c;体型大小不一。它们通常拥有长条的身体、四肢和尾巴&#xff0c;鳞片覆盖全身&#xff0c;这使得它们能够在各种环境中轻松移动。大多数蜥蜴拥有…...

2020年认证杯SPSSPRO杯数学建模C题(第一阶段)抗击疫情,我们能做什么全过程文档及程序

2020年认证杯SPSSPRO杯数学建模 C题 抗击疫情&#xff0c;我们能做什么 原题再现&#xff1a; 2020 年 3 月 12 日&#xff0c;世界卫生组织&#xff08;WHO&#xff09;宣布&#xff0c;席卷全球的冠状病毒引发的病毒性肺炎&#xff08;COVID-19&#xff09;是一种大流行病。…...

Java技术栈 —— Hadoop入门(一)

Java技术栈 —— Hadoop入门&#xff08;一&#xff09; 一、Hadoop第一印象二、安装Hadoop三、Hadoop解析3.1 Hadoop生态介绍3.1.1 MapReduce - 核心组件3.1.2 HDFS - 核心组件3.1.3 YARN - 核心组件3.1.4 其它组件3.1.4.1 HBase3.1.4.2 Hive3.1.4.3 Spark 一、Hadoop第一印象…...

Shell脚本小游戏:石头剪刀布

脚本代码&#xff1a; #!/bin/bash echo "接下来的是石头剪刀布的游戏" echo "定义1&#xff1a;包子&#xff1b;2&#xff1a;剪刀&#xff1b;3&#xff1a;布" echo "------------------------------" NUMecho $[RANDOM%31] #1包子 #2剪刀…...

Windows10系统的音频不可用,使用疑难解答后提示【 一个或多个音频服务未运行】

一、问题描述 打开电脑&#xff0c;发现电脑右下角的音频图标显示为X&#xff08;即不可用&#xff0c;无法播放声音&#xff09;&#xff0c;使用音频自带的【声音问题疑难解答】&#xff08;选中音频图标&#xff0c;点击鼠标右键&#xff0c;然后选择“声音问题疑难解答(T)”…...

Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明

1 前言 角色在地图上移动到岩石后面时&#xff0c;完全被岩石遮挡&#xff0c;玩家只能看到岩石。这逻辑看起来没问题&#xff0c;但并不是玩家想要看到的画面&#xff0c;玩家更希望关注角色的状态 为了避免角色被遮挡&#xff0c;可以使用 Cinemachine Collider 功能&#x…...

ResNet论文阅读和简单实现

论文&#xff1a;https://arxiv.org/pdf/1512.03385.pdf Deep Residual Learning for Image Recognition 本模块主要是阅读论文&#xff0c;会做简单的翻译&#xff08;至少满足我自己能看明白&#xff09;。 Introduction 由上图可见&#xff0c;在20层和56层的网络上训练的…...

QT上位机开发(数据库sqlite编程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 编写软件的时候&#xff0c;如果用户的数据比较少&#xff0c;那么用json保存是非常方便的。但是一旦数据量大了之后&#xff0c;建议还是用数据库…...

在ARMv8中aarch64与aarch32切换

需求描述 在项目调试过程中,由于内存或磁盘空间不足需要将系统从aarch64切换到aarch32的运行状态去执行,接下来记录cortexA53的调试过程。 相关寄存器描述 ARM64: SPSR_EL3 N (Negative):表示运算结果的最高位,用于指示运算结果是否为负数。 Z (Zero):表示运算结果是否…...

拧巴的 tcp

本来想说说 tcp fastopen(tfo)&#xff0c;但没什么意义&#xff0c;看 rfc7413 好了&#xff0c;还是 tcp 的惯常套路&#xff0c;引入一个新特性&#xff0c;解决了某个问题&#xff0c;带来一些新问题&#xff0c;然后就是各种 tradeoff&#xff0c;哪里适用哪里不适用。久而…...

java servlet 学生管理系统myeclipse开发oracle数据库BS模式java编程网

一、源码特点 java servlet 学生管理系统是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助servletbeandao (mvc模式开发)&#xff0c;系统具有完整的源代码和数据库&#xff0c;开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Oracle 10g…...

使用buildx构建多架构镜像

使用buildx构建多架构镜像 1. 前置条件 docker 19.03以上版本 ubuntu 22.04 2. 安装相关组件 2.1 安装docker sudo apt-get updatesudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-commoncurl -fsSL https://mirrors.…...

Crow:run的流程4 准备接收http请求

完成tcp的accept后,下一步需要接收tcp的数据,同时完成http的分析 class Connection { public:void start(){adaptor_.start([this](const asio::error_code& ec) {if (!ec){start_deadline();parser_.clear();do_read();}else{CROW_LOG_ERROR << "Could not …...

Springboot集成RabbitMq一

0、知识点 1、创建项目-生产者 默认官方start.spring.io已不支持自动生成低版本jkd的Spring项目&#xff0c;自定义用阿里云的starter即可&#xff1a;https://start.aliyun.com 2、创建配置类 package com.wym.rabbitmqprovider.utils;import org.springframework.amqp.core.…...

零知识证明(zk-SNARK)- groth16(一)

全称为 Zero-Knowledge Succinct Non-Interactive Argument of Knowledge&#xff0c;简洁非交互式零知识证明&#xff0c;简洁性使得运行该协议时&#xff0c;即便 statement 非常大&#xff0c;它的 proof 大小也仅有几百个bytes&#xff0c;并且验证一个 proof 的时间可以达…...

费县做网站/网站整站优化

之前也没写过什么博客&#xff0c;可能文章结构比较混乱&#xff0c;想到那写到哪。主要是把自己学习中的经验写下来。为什么选择laravel框架&#xff0c;是因为laravel框架目前是Php最流行的框架&#xff0c;深入研究后发现和asp.net mvc框架在功能上基本上是伯仲之间。只是各…...

微信导购网站怎么做视频教学/磁力搜索

OSI model&#xff08;open system interconnection&#xff09;存在的原因&#xff1a; 网络模型建立是为了是网络的建造者可以建造出可以相互交流和一起工作的网络&#xff0c;并且描述了从一个电脑上通过网络传数据到另一个网络。 1.physical层 定义了对终端系统之间的连接的…...

wordpress 萌/百度推广优化中心

今天在写代码是遇到这个错误。 Type ‘..’ cannot be ISerializable and have DataContractAttribute attribute. 只是因为在一个类里面同时使用.Net 1.1 的XmlSerializer 和.NET 3.5的DataContractAttribue所导致的。这是不同版本的Framework对于序列化一个Object实现的不同技…...

做logo设计的网站/哪家网络营销好

有时候&#xff0c;我们导入一个项目的时候会发现tomcat或者jboss不能识别它&#xff0c;因为它不是动态web项目&#xff0c;所以就不能部署到服务器上&#xff0c;这时候就要修改java项目&#xff0c;让它变成web项目。 有两种方法&#xff0c;第一种是新建一个web项目&#…...

如何做自己的网站/新一轮疫情最新消息

最近在做项目时&#xff0c;运用了VS2008 中 Team Foundation Server 版本控制工具&#xff0c;在修改后本地文件不能编译&#xff0c;不能从服务器端下载 &#xff0c;就想重新建立一个本地目录&#xff0c;从服务器端获取新的文件。弄了个吧小时才解决这个问题。 From the Fi…...

就业服务网站建设方案/如何在百度上推广自己

介绍template是微信小程序提供的模板&#xff0c;可以在模板中定义代码片段&#xff0c;然后在不同的地方调用。 简单使用定义template因为项目中可能会需要到不止一个template&#xff0c;所以最好新建一个文件夹来存放template相关的文件。注意这里只是单独的创建各个文件&am…...