【SpringCloud】企业认证、分布式事务,分布式锁方案落地-2

目录

高并发缓存三问 - 穿透

缓存穿透

概念

现象举例

解决方案

缓存穿透 - 预热架构

 缓存穿透 - 布隆过滤器

布隆过滤器

布隆过滤器基本思想​编辑

了解

高并发缓存三问 - 击穿

缓存击穿

高并发缓存三问 - 雪崩

缓存雪崩

解决方案

总结

 为什么要使用数据字典?

创建数据字典

 查询数据字典列表

修改删除数据字典

修改

删除

用户端查询数据字典列表

缓存同步策略

Canal工作原理与Binlog

Canal

Binlog是什么

Binlog类别

官方参考

Canal监听同步流程

开启MySql的binlog

步骤1 - 开启mysql的biglog模式

安装配置Canal

 SpringBoot集成Canal实现监听

anal实现0侵入缓存同步 - 新增同步

Canal实现0侵入缓存同步 - 删除与修改

作业:缓存预热 - 刷入数据字典缓存数据​编辑

发起审核创建公司

Feign远程查询企业HR数

远程调用

上传企业授权书​编辑

绑定企业HR信息

 提交企业审核Seata日期转换采坑

刷新用户最新信息

HR查询企业审核状态


高并发缓存三问 - 穿透

缓存穿透

概念

缓存穿透:是指查询一个在数据库中不存在的数据,缓存和数据库中都不会命中(也就是都查询不到),在我们编写代码的时候,一般数据库查询不到的是不会写入到redis的,但是前端请求却会绕过redis直接打在数据库上,高并发时造成数据库宕机。如此一来,就失去了redis存在的意义,往往黑客可能会处于某种目的来攻击服务器,又或者一些爬虫系统也会造成这个现象的出现。

可以看一下如下架构图,从图中可以看到,如果redis中没有这个key,那么所有请求都会绕过reids去访问数据库。

现象举例

打开淘宝,可以看到有很多分类。对于分类,我们可以把它们作为数据字典存储在数据库,然后再放入到缓存。当请求过来的时候直接查缓存就行了。

随便打开某一个分类,这个红框内每个分类都不一样,可以推断是分类的id。

这个id必须要缓存,肯定不可能查库的。但是这个id存在缓存的话,是可以查询到的。但是如果没有呢?没有的话如果代码逻辑不好就可能直接打在数据库上来。
我们来改一下这个id,随便改为一个不存在的数字,看看会发生什么变化:

这个时候直接跳转为404的页面了,因为不存在啊,所以返回了一个错误页面。

上面的流程是没有问题的,但是我们在编写代码的时候,可能会造成缓存穿透。可以看如下代码:

上面的红框代码,很有可能是我们平时会做的一个步骤,判空操作,但是正因为判空了,不往redis中设置,那么最后再查询的时候,redis反而会没有值,从而被请求绕过,进入到数据库。

解决方案

  • 对不存在的key做空值处理。(不管是否为空,都存在redis中)

缓存穿透 - 预热架构

  • 缓存预热。在项目启动的时候,预先把数据库的热点数据放入redis中,在前端请求的时候,只查redis,不查数据库。那么如此一来,哪怕查到空值,也不会绕过了redis,请求也不会到数据库了。

可以构建一个缓存服务,它是一个微服务节点,里面包含了很多的接口,比如刷新行业,可以直接手动发一个get请求某个接口,则刷新行业数据,或者其他数据都行,因为我们是直接查询redis的,把redis作为数据库,所以一旦有些数据在数据库里更新了,为了测试方便,我们会手动更新,也方便在线上的时候也能手动更新一些数据。

 缓存穿透 - 布隆过滤器

  • 布隆过滤器:布隆过滤器可以查询并且判断某个key一定不存在,但是不能判断某个值一定存在

布隆过滤器

  • 致命弱点:

    • 无法删除
    • 误判率

    我们是做物流的,3天前的车和货,是属于过期信息,是要删除,删除以后就是不存在了,那么布隆过滤器无法删除。

    代码不去写了,只需要知道原理是啥就行了,面试的时候大概率会被问到。

布隆过滤器基本思想

了解

布谷鸟过滤器:原理同布隆过滤器,优点是可以删除

高并发缓存三问 - 击穿

缓存击穿

如上图,redis作为数据库的前置缓存,抵挡一部分的流量,我们设置数据的时候往往都是 KV 键值对,他是可以设置一个expire的有效时间的。之前我们有讲过redis的过期key策略(LRU/LFU),当一个key成为冷缓存了,那么他会有可能被清理掉,对吧。 假设这个时候,正好用户会大量请求刚刚所说的那个key的缓存数据,但是他被清理掉了,这个时候会发生什么情况?看如下图:

这个时候,用户的请求无法从redis中获得缓存数据,那么此时由于并发量十分巨大,所有的查询请求都落在了数据库上,造成数据库压力巨大,db会极易挂掉。那么这就是缓存击穿现象。 缓存击穿需要满足两个前置条件:

  1. 请求高并发;
  2. 正好某个key失效了,或者由于过期策略被删除了,还没来得及把数据缓存进redis的那一瞬间的时间。

既然有这样的现象出现,并且对整个系统造成一定的影响,如何解决?有木有解决方案?其实我们的目标其实就是要隔断请求,防止请求击穿。方案有如下:

  • 由于redis是单线程的,用户请求其实是排队一个个去访问redis,那么可以让第一个请求在从redis里查询key没有后,setnx一下,如果setnx成功,则去查询数据库,查询到数据后重新设置到缓存中。如果后面的请求setnx失败,则可以让他们sleep一下,比如随机1秒以内的时间,随后再去重复检查,直到有key被重新设置进redis,那么这么一来,不论有1万个还是1亿个请求,都只会有1个请求打到数据库,这样就保护了redis。
    • 但是这么做会有问题,就是如果在setnx之后,第一个请求后续操作失败了,那么setnx得不到释放,造成死锁,这样可以通过设置setnx的过期时间来做,如果第一个请求失败了,那么通过过期时间来释放锁也OK的。
    • 当然更好的方式就是用多线程的方式来做,1个线程用于去请求数据库,第二个线程用于定时检查数据是否成功被设置进redis,如果没有,就适当延长setnx的过期时间,去重置它。为什么要这么做,因为查询数据库,有时候可能会有拥堵现象,当然这么做了,业务代码会相当多也比较复杂。
  • 设置永不过期,如果你的内存够大,或者说缓存本来也不多,内存空间充足,那么所有key都是永不过期的,那么这样的击穿情况也不会出现。
  • 缓存预热,在项目初期就已经把所有需要用到的数据放入到redis中,用户请求查询的时候只查redis,哪怕key不存在,也不会请求到数据库的,这样是完全进行了隔断,保证不会出现击穿现象。

高并发缓存三问 - 雪崩

缓存雪崩

雪崩和之前的击穿有点类似,击穿是一个key失效,而雪崩是有大量的key同时过期,因为一个redis其实很庞大,免不了会有很多的key会同时到期的,这样用户请求像个散弹枪一样打在数据库上。

如何预防?

  • 均匀的随机的分配key的过期时间
  • 缓存预热

第二种情况的雪崩就是和时间相关的,比如有些金融项目,前一天和后一天的一些相关金融业务数据啊,计算比例,利率啊啥的,每天都不一样,前一天的会在零点或者凌晨1点全部失效,那么这个时候咋办?两种方案:

  • 在零点统一失效后,做个定时任务,跑一遍所有涉及到redis的接口,访问一遍,这么一来涉及到的缓存数据在查询db后会放入到redis中,那么这种方式比较low。
  • 第二种,就是你的key携带日期,比如可以这么设置:
    key=sales:amount-percent:20200505,
    value=0.98
    key=sales:amount-percent:20200506,
    value=0.965
    如此一来,在时间一过零点,获得的数据就可以立马生效,这样也就是提前设置好第二天的数据,前一天的所有数据全部失效就无所谓了。
  • 其实还有一种方式,也捎带说一下,这种方式的业务代码相对复杂一些,就是你在零点这个失效点过后,业务层的读取redis数据做延时,只放一部分的请求过去,避免请求大量访问到数据库,待redis缓存设置好以后,后续的请求才会放行。这种方式也可以,了解一下即可。

解决方案

  1. 集群高可用,哨兵或Cluster
    1. 目的,保证最基本的高可用
    2. redis的持久化,再此回复后,缓存数据重新加载
  2. Redis + Ehcache 两两结合,不把鸡蛋放在同一个篮子里
    1. 第一次请求数据库,数据放入redis和ehcache
    2. 以后的请求,会先请求ehcache,如果有返回,如果没有,查询redis,如果有返回,如果没有再查看
    3. 虽然,ehcache没有redis那么强大,但是有缓存总比没有来的好。目的:两两保障
  3. 限流,限制大流量,我只保证一部分的用户可以正常的访问,而不至于整体奔溃
    1. 只接受更小流量的请求,这样数据库可以处理应付的过来
    2. 目的,让系统整体还能运作起来,赚小钱总比不赚来的好,系统也不会崩。
    3. 举例:一艘船,只能做1000人,来了1万人,我只开放1000人的票,不然1万人都来了,船就沉了。
  4. 降级,限流在外的请求,没有处理,这个时候会引导至一些简单的信息提示页面,可以友情提示说请稍后啊之类的。甚至404也行。
    1. 限流+降级保证数据库肯定能够运转的过来。
    2. 少赚钱总比不赚钱要来的好
    3. 保证一部分用户能够真正的被系统处理。

总结

一定要保证数据库不能死,数据库死了资损会相当严重,所以限流+降级是必要的手段。

 为什么要使用数据字典?

前面我们围绕的都是和缓存相关的内容,那么业务层面,目前行业分类就已经OK了。

接下来,再来看数据字典。先看如下表,平时我们做一些分类选择的时候,可能都会创建诸如以下这样的表,这不仅仅是人员规模,像企业福利待遇企业标签等等,都可以设计这样的表。


但是,像这样的表虽然可以用,但是如果一个系统,或者我们很多系统都要设计类似的表,但是业务点有很多,我们可能需要设计五六十张类似的表甚至上百张表,很显然,太多了,也不好管理。这个时候,数据字典的需求就出现了。

我们平时使用新华字典的时候,是可以根据拼音或者偏旁来进行搜索查询的,同理,我们能不能也根据不同数据的类别来分类汇总后进行筛选能?很明显,是可以的,所以我们完全可以通过一张表来管理所有的分类数据,这样就更能够便于我们对所有字典数据的管理了,查询起来也不会有太大的麻烦,也节约了表空间。可以做出如下的设计:

最终,我们开发成如下的功能结构就行了:

附带一提,我们以前的数据字典是一个独立的服务,专门提供给其他系统做字典类别查询使用的,不仅仅只是自己的本系统,公司的所有项目都可以依赖这个数据字典服务。而且,我们的国际化,也是通过数据字典来做的。

创建数据字典

BO直接复制:

service与mapper直接从逆向工具复制过来。

创建Controller:

创建接口:

 查询数据字典列表

controller:

service:

修改删除数据字典

修改

先查询,后修改:

删除

用户端查询数据字典列表

作业:自己结合之前做行业列表的时候,结合redis来实现接口的查询调用。

缓存同步策略

之前我们所做的,都是手动同步,不管是双删还是延迟队列。其实这种方式都不太好。接下来来我们看看如何自动同步缓存。

  • 手动同步,过期时间:简单方便,但是时效性不及时,需要等到过期后才能查询到新的数据,而且有可能发送缓存击穿问题。
  • 缓存双写双删:修改数据库的同时修改缓存,非常及时,缓存时效是最新的。但是代码耦合度很高,对代码的侵入性很强烈,我们之前所写的代码就是如此,太过于冗余了,裹脚布一样,又臭又长。
  • 定时、(异步)延迟同步:低耦合,代码入侵少,可以同时对多个存储介质进行数据的更新,比如更新数据库的同时修改redis、mongodb、elasticsearch等,只需要一行代码发一个消息就行。但是时效性相对有一点点偏差,也就是中间同步过程有一定的数据不一致状态,同步完成后可以达到一致,在非金融场景业务下使用较多,多存储介质也可以使用。
  • 0侵入自动同步:MQ异步同步可以做到一行代码解耦,代码入侵就少了,如此之外,其实还有一种0侵入方案。那就是canal异步监听,他是阿里巴巴的一个开源工具。

Canal工作原理与Binlog

Canal

阿里因为自身的业务需求,需要把国内数据同步给国外,所以他们是异地机房的数据同步需求问题,他们通过对数据库日志的解析,可以获得增量的变更,对此变更在进行数据同步,所以就衍生出了数据订阅和消费的中间件,也就是Canal同步工具。
Canal是基于java开发的中间件,主要支持对mysql的binlog进行解析,解析完成后再利用客户端工具来获得相关的数据,增删改的数据都可以。

Binlog是什么

全称是binary-log,二进制日志。

Canal是通过解析mysql的日志来进行数据同步的,那么日志其实就是binlog,也就是mysql的二进制日志,他会记录所有非查询语句(增删改),也会包含操作的执行消耗的时间,另外mysql的binlog日志是事务安全的。

一般来说,开启binlog的话呢,其实也会有一定的性能损耗的,因为本来是不要的,现在开启了,那么他就需要耗费经理去做别的事,就跟你老板让你加班多做点事一样,你的时间精力自然就流失了。
binlog有两个非常重要的目的:

  • 数据库可以搭建主从,主从同步就是把master的binlog传递给slave来进行数据同步达到一致性的。
  • 数据恢复,可以通过binlog进行恢复。我以前的私活就是遇到过,人家以为mysql是流氓软件结果直接删了,但是binlog还在,所以我给他恢复了数据,硬生生含泪收了几千块钱。。。

Binlog类别

  • statement:记录每次增删改的语句,空间占用会比较节省。但是,数据恢复的时候可能会产生不同数据,因为执行的时间不同,尤其是now()这个函数的获取,所以为什么会有同学问我不使用数据库自己的时间,而是要通过我们手动在业务层去设置时间的原因。
  • mixed:可以认为是混合模式,一定程度上能解决不一致问题,此外在进行函数使用的时候会按照row的模式进行处理。但是某些情况之下,不一致的情况还是依然存在的。
  • row:行级别,biglog会记录每次操作后每行记录的变化。可以保证绝对的数据一致性,因为他只记录执行后的结果。缺点就是占用空间会大一些,但是磁盘空间是可以用钱解决的,能用钱解决的问题就不是问题。

这个有点类似与redis的存储模式,也就是rdb和aof以及混合模式。面试的时候可能会被问到,大家务必理解。

官方参考

https://github.com/alibaba/canal

Canal功能实现(使用场景):

  • 数据库镜像
  • 数据库实时备份
  • 索引构建和实施维护
  • 业务缓存刷新
  • 带业务逻辑的增量数据处理
  • 数据实时统计,大屏实时展示(数据采集)

数据库的实时备份是很有用的,以前我们客户就提出过这样的要求,而且我自己接的私活也有这样的要求,所以正因为canal,我们可以多赚一点。

Canal监听同步流程

参考如下图:

Canal可以监听数据库的变化,此时我们业务层代码是不需要有变动的,做好数据层面的监听,如果监听到数据变动了,比如增删改了,那么则在缓存中就可以做出对应的修改逻辑就行了。

所以,我们后面就会使用canal来落地实现咱们的0侵入方案,而且这种方案的时效性也比mq异步方案更好一些。

开启MySql的binlog

https://github.com/alibaba/canal/wiki/QuickStart

步骤1 - 开启mysql的biglog模式

并修改配置文件,添加如下内容:

[mysqld]
log-bin=/var/lib/mysql/mysql-bin # 开启 binlog,位置使用我们一开始配置的文件挂载位置
binlog-format=ROW # 选择 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定义,不要和 canal 的 slaveId 重复

# 表示当前数据库开启biglog,不配置,表示所有数据库都开启
binlog-do-db=imooc-hire-dev

重启mysql:

docker restart mysql

查看data目录,会有一些biglog文件:

  • *.index是二进制的索引文件,用于记录所有的二进制文件。
  • *.00000这个就是二进制文件,记录所有的增删改语句事件。

检测binlog是否开启,在navcat中查询:

show variables like '%log_bin%'

创建账号并且授权:

CREATE USER canal IDENTIFIED BY 'canal';  
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;

file:文件名
postion:日志的偏移量,主从差异就是根据这个来,可以理解为offset

安装配置Canal

docker pull canal/canal-server:v1.1.6
运行:

docker run -p 11111:11111 \
--name canal \
-e canal.destinations=imooc \
-e canal.instance.mysql.slaveId=20231111 \
-e canal.instance.master.address=192.168.1.121:3306 \
-e canal.instance.dbUsername=canal \
-e canal.instance.dbPassword=canal \
-e canal.instance.connectionCharset=UTF-8 \
-e canal.instance.filter.regex=imooc-hire-dev.data_dictionary \
--restart=always \
-d canal/canal-server:v1.1.6
  • 11111:11111:端口映射
  • –name canal:容器名称
  • –restart=always:自动重启
  • canal.destinations:集群名称,给集群取一个名字
  • canal.instance.mysql.slaveId:区别master的id,保证唯一
  • canal.instance.master.address:mysql主数据库地址
  • canal.instance.dbUsername/dbPassword:用户名和密码,也就是之前上一节课所创建的用户以及授权,如果设置root用户其实也行。
  • canal.instance.connectionCharset:字符集
  • canal.instance.filter.regex:监听数据库数据表的表达式,多个可用逗号,连接

以上环境变量如果不设置,也可以,但是需要在canal内部去修改canal-server配置也是OK的。

最后查看是否运行成功日志:

docker logs -f canal

如下命令,可以进入canal容器内部:

docker exec -it canal bash
进入目录并且查看日志:

发现一个错误,这是mysql8的密码加密方式问题:

重新通过navcat更新密码:

ALTER USER 'canal'@'%' IDENTIFIED WITH mysql_native_password BY 'canal';
FLUSH PRIVILEGES;

查看结果:

docker restart canal

再次查看日志:

随后,随意修改数据字典中的任意记录,再次查看日志:

 SpringBoot集成Canal实现监听

官网地址:GitHub - NormanGyllenhaal/canal-client: spring boot canal starter 易用的canal 客户端 canal client

在资源服务中添加依赖:

<dependency><groupId>top.javatool</groupId><artifactId>canal-spring-boot-starter</artifactId><version>1.2.1-RELEASE</version>
</dependency>

这个依赖要比官方的依赖好用一些。(最新的在maven仓库中目前下下载不来,只能使用老版本)

配置yml文件:

创建canal监听助手类:

创建一个canal映射对象,字段需要和数据库保持一致,否则监听不到

避免过多的打印日志信息:增删改后的测试

anal实现0侵入缓存同步 - 新增同步

继承通用属性和声明缓存前缀:新增:

Canal实现0侵入缓存同步 - 删除与修改

删除:修改:

前端app查询:

作业:缓存预热 - 刷入数据字典缓存数据

  • 增加一个按钮,叫做“刷新缓存”
  • 点击后,把所有不同类别的数据字典以list形式存入缓存,此功能作为缓存预热。因为目前我们的数据字典数据都是通过sql脚本导入的,不能通过canal监听来同步数据。

删除数据字典表,重新以sql的脚本导入,此刻因为有canal了,也会监听到数据,从而刷入缓存中。

那么如此canal就在咱们这章节全部讲完,本来是要在后俩周讲的,这边前置了也没关系,canal在多级缓存的时候用来同步也是非常不错的。

发起审核创建公司

controller

service

Feign远程查询企业HR数

controller:

获得企业信息的公用方法:

private CompanySimpleVO getCompany(String companyId) {if (StringUtils.isBlank(companyId)) {return null;}String companyJson = redis.get(REDIS_COMPANY_BASE_INFO + ":" + companyId);if (StringUtils.isBlank(companyJson)) {// 为空,查询数据库Company company = companyService.getById(companyId);if (company == null) {return null;}CompanySimpleVO companySimpleVO = new CompanySimpleVO();BeanUtils.copyProperties(company, companySimpleVO);redis.set(REDIS_COMPANY_BASE_INFO + ":" + companyId,new Gson().toJson(companySimpleVO),8 * 60 * 60);return companySimpleVO;} else {// 不为空,转换为对象return new Gson().fromJson(companyJson, CompanySimpleVO.class);}
}

service:

远程调用

controller:

 时间到了,容易造成缓存击穿 

service:feign:别忘记在yml中添加redis的配置!!!

上传企业授权书

绑定企业HR信息

feign:

controller:

service:

企业服务调用:

企业表信息:

 提交企业审核Seata日期转换采坑

service:

分布式事务测试用seata测试是否成功回滚。

刷新用户最新信息

为了让用户信息在本地刷新,可以重新刷新一下,或者用户重登陆,在这里我们选择前者。

controller:

HR查询企业审核状态

获得企业信息,主要可以查询到企业的审核状态

企业controller:

提问:为什么这里通过用户id查询而不是企业id查询呢?企业id不是可以直接在用户信息中获得吗?
答曰:因为企业和用户可能会解绑,一旦解绑,但是前端可能也会缓存早期的企业信息,如此一来,这样前端会无法获得正确的企业信息。当然,偷懒的做法就是直接通过企业id去查,这是最简单的。

用户controller:feign:

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

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

相关文章

【Dison夏令营 Day 30】如何用 Python 创建平台游戏(下篇)

几十年来&#xff0c;平台游戏一直是深受玩家喜爱的游戏类型&#xff0c;它提供了令人兴奋的挑战和令人怀念的游戏玩法。在本教程中&#xff0c;我们将指导您使用 Python 中的 PyGame 库构建自己的平台游戏。 无论您是希望深入游戏开发的初学者&#xff0c;还是希望探索 Pygame…

【OpenCV C++20 学习笔记】基本图像容器——Mat

【OpenCV C20 学习笔记】基本图像容器——Mat 概述Mat内部结构引用计数机制颜色数据格式 显式创建Mat对象使用cv::Mat::Mat构造函数矩阵的数据项 使用数组进行初始化的构造函数cv::Mat::create函数MATLAB风格的初始化小型矩阵通过复制创建Mat对象 Mat对象的输出其他普通数据项的…

77.WEB渗透测试-信息收集-框架组件识别利用(1)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;76.WEB渗透测试-信息收集- WAF、框架组件识别&#xff08;16&#xff09; java&#xff…

HarmonyOS入门-状态管理

View(UI)&#xff1a;UI渲染&#xff0c;指将build方法内的UI描述和Builder装饰的方法内的UI描述映射到界面。 State&#xff1a;状态&#xff0c;指驱动UI更新的数据。用户通过触发组件的事件方法&#xff0c;改变状态数据。状态数据的改变&#xff0c;引起UI的重新渲染。 装…

C# Nmodbus,EasyModbusTCP读写操作

Nmodbus读写 两个Button控件分别为 读取和写入 分别使用控件的点击方法 ①引用第三方《NModbus4》2.1.0版本 全局 public SerialPort port new SerialPort("COM2", 9600, Parity.None, 8, (StopBits)1); ModbusSerialMaster master; public Form1() port.Open();…

UWA Gears正式上线,助力移动平台性能优化

亲爱的开发者朋友们&#xff0c; 我们非常激动地向大家宣布&#xff0c;UWA最新的无SDK性能分析工具 - UWA Gears&#xff0c;现已正式发布&#xff01;无论您使用的是哪种开发引擎&#xff0c;这款工具都能轻松应对&#xff0c;为您的项目保驾护航。更令人心动的是&#xff0c…

后台管理系统登录安全和权限要求

一、前言 几乎所有的系统都有后台管理系统&#xff0c;后台登录需要账号和密码&#xff0c;后台管理员权限需要有控制。所有管理员的操作都应该有操作日志。 二、存在的问题 现在很多系统只需要账号和密码就能登录&#xff0c;有的还是简单账号和简单密码&#xff0c;就是弱口…

虚拟机之ip配置,ssh连接到虚拟机

右边是我的虚拟机&#xff0c;左边是我使用vscode来连接&#xff08;终端也可以。然后注意vscode配置后点一下刷新&#xff0c;不会自动刷新的QA&#xff09;&#xff08;吐槽一下&#xff0c;虚拟机都不能复制内容呢&#xff0c;确实仿真&#xff0c;centos仿真就是因为没有图…

二手车小程序

本文来自&#xff1a;FastAdmin二手车小程序 - 源码1688 一款基于ThinkPHPFastAdmin开发的原生微信小程序二手车管理系统。 前端小程序码&#xff1a; 后台演示地址&#xff1a; https://facars.site100.cn/OHNYSKzuba.php/carswxsys/sysinit?refaddtabs

视觉巡线小车——STM32+OpenMV(四)

目录 前言 一、整体控制思路 二、代码实现 1.主函数 2.定时器回调函数 总结 前言 通过以上三篇文章已将基本条件实现&#xff0c;本文将结合以上内容&#xff0c;进行综合控制&#xff0c;实现小车的视觉巡线功能。 系列文章请查看&#xff1a;视觉巡线小车——STM32OpenMV系列…

【轨物方案】电表红外抄表物联网装置

对于光伏运维工程师来说&#xff0c;电表抄表是一件并不陌生的工作&#xff0c;不过很多并网电表的RS485通讯接口一般都被占用了&#xff0c;并且电表的外壳也被铅封起来。在这种情况下电站通常采用人工抄表的方式采集电量数据&#xff0c;这种方式费时费力&#xff0c;对电站运…

京东科技集团将在香港发行与港元1:1挂钩的加密货币稳定币

据京东科技集团旗下公司京东币链科技(香港)官网信息&#xff0c;京东稳定币是一种基于公链并与港元(HKD) 1:1挂钩的稳定币&#xff0c;将在公共区块链上发行&#xff0c;其储备由高度流动且可信的资产组成&#xff0c;这些资产安全存放于持牌金融机构的独立账户中&#xff0c;通…

【OpenCV C++20 学习笔记】扫描图片数据

扫描图片数据 应用情景图像数据扫描的难点颜色空间缩减&#xff08;color space reduction&#xff09;查询表 扫描算法计算查询表统计运算时长连续内存3种扫描方法C风格的扫描方法迭代器方法坐标方法LUT方法 算法效率对比结论 应用情景 图像数据扫描的难点 在上一篇文章《基…

OAK-FFC 分体式相机使用入门介绍

概述 OAK FFC 主控板和多种可选配镜头模组非常适合灵活的搭建您的3D人工智能产品原型。由于镜头是分体式的&#xff0c;因此你可以根据需要测量的距离&#xff0c;自定义深度相机安装基线&#xff0c;并根据你的项目要求&#xff08;分辨率、快门类型、FPS、光学元件&#xff…

FPGA教程|零基础到实战的全方位指导

在数字化时代&#xff0c;FPGA&#xff08;现场可编程门阵列&#xff09;作为一种灵活的硬件编程平台&#xff0c;正逐渐成为电子工程师和计算机科学家必备的技能之一。无论你是电子专业的学生&#xff0c;还是职场中的工程师&#xff0c;掌握FPGA开发技术&#xff0c;都将为你…

前端与HTML

前端与HTML 什么是前端&#xff1f; 解决GUI人机交互问题跨终端&#xff08;PC/移动浏览器&#xff09;&#xff08;客户端小程序&#xff09;&#xff08;VR/AR等&#xff09;Web技术栈 前端工程师&#xff1a;利用web技术栈解决多端图形界面用户交互的工程师 前端技术栈 …

CDGA|数据治理:安全如何贯穿数据供给、流通、使用全过程

随着信息技术的飞速发展&#xff0c;数据已经成为企业运营、社会管理和经济发展的核心要素。然而&#xff0c;数据在带来巨大价值的同时&#xff0c;也伴随着诸多安全风险。因此&#xff0c;数据治理的重要性日益凸显&#xff0c;它不仅仅是对数据的简单管理&#xff0c;更是确…

rv1126物体检测 rkmedia、opencv……

整体码流流向&#xff1a; 因此代码也分为这几部分&#xff1a; VI&#xff1a;采集视频 配置视频采集信息 模型推理线程&#xff1a;获取VI码流、载入模型、进行模型推理、保存推理结果 画框线程&#xff1a;获取VI码流、获取推理结果、显示推理结果、输出码流到VENC VENC…

如何使用C#快速创建定时任务

原文链接&#xff1a;https://www.cnblogs.com/zhaotianff/p/17511040.html 使用Windows的计划任务功能可以创建定时任务。 使用schtasks.exe可以对计划任务进行管理&#xff0c;而不需要编写额外代码 这里掌握schtasks /CREATE 的几个核心参数就可以快速创建计划任务 /SC …

论文总结:A Survey on Evaluation of Large Language Models-鲁棒性相关内容

A Survey on Evaluation of Large Language Models 只取了鲁棒性相关的内容 LLMs&#xff1a;《A Survey on Evaluation of Large Language Models大型语言模型评估综述》理解智能本质(具备推理能力)、AI评估的重要性(识别当前算法的局限性设 3.2.1 Robustness鲁棒性&#xf…