【云岚到家】-day03-门户缓存实现实战

【云岚到家】-day03-门户缓存实现实战

1.定时任务更新缓存

1.1 搭建XXL-JOB环境

1.1.1 分布式调度平台XXL-JOB介绍

对于开通区域列表的缓存数据需要由定时任务每天凌晨更新缓存,如何实现定时任务呢?

1.使用jdk提供的Timer定时器

示例代码如下:

每个Timer对应一个线程,可以同时启动多个Timer定时执行多个任务

public static void main(String[] args){  Timer timer = new Timer();  timer.schedule(new TimerTask(){@Override  public void run() {  //TODO:something}  }, 1000, 2000);  //1秒后开始调度,每2秒执行一次
}

Time使用简单,可以实现每隔一定的时间去执行任务,但无法实现每天凌晨去执行任务,即在某个时间点去执行任务

2.使用第三方Quartz方式实现

Quartz 是一个功能强大的任务调度框架,它可以满足更多更复杂的调度需求,Quartz 设计的核心类包括 Scheduler, Job 以及 Trigger。其中,Job 负责定义需要执行的任务,Trigger 负责设置调度策略,Scheduler 将二者组装在一起,并触发任务开始执行。Quartz支持简单的按时间间隔调度、还支持按日历调度方式,通过设置CronTrigger表达式(包括:秒、分、时、日、月、周、年)进行任务调度

虽然Quartz可以实现按日历调度的方式,但无法支持分布式环境下任务调度。分布式环境下通常一个服务部署多个实例即多个jvm进程,假设运营基础服务部署两个实例每个实例定时执行更新缓存的任务,两个实例就会重复执行。如下图:

在这里插入图片描述

3.使用分布式调度平台XXL-JOB

在分布式环境下进行任务调度需要使用分布式任务调度平台,XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用

官网:https://www.xuxueli.com/xxl-job/

文档:https://www.xuxueli.com/xxl-job/#%E3%80%8A%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E5%B9%B3%E5%8F%B0XXL-JOB%E3%80%8B

XXL-JOB有调度中心,可以安排两个人做任务,但不是同时做,一个人挂了,就让另外一个人做任务

XXL-JOB主要有调度中心、执行器、任务:

在这里插入图片描述

调度中心:

负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码;

主要职责为执行器管理、任务管理、监控运维、日志管理等

任务执行器:

负责接收调度请求并执行任务逻辑;

主要职责是执行任务、执行结果上报、日志服务等

使用XXL-JOB就可以解决使用多个jvm进程重复执行任务的问题,如下图:

在这里插入图片描述

XXL-JOB调度中心可以配置路由策略,比如:第一个、轮询策略、分片等,它们分别表示的意义如下:

第一个:即每次执行任务都由第一个执行器去执行。

轮询:即执行器轮番执行

分片:每次执行任务广播给每个执行器让他们同时执行任务(一起干活)

如果根据需求每次执行任务仅由一个执行器去执行任务可以设置路由策略:第一个、轮询

如果根据需求每次执行任务由多个执行器同时执行可以设置路由策略为:分片

1.1.2 部署调度中心

1.查阅xxl-job的源码

首先下载XXL-JOB

GitHub:https://github.com/xuxueli/xxl-job

码云:https://gitee.com/xuxueli0323/xxl-job

项目使用2.3.1版本: https://github.com/xuxueli/xxl-job/releases/tag/2.3.1,使用IDEA打开解压后的目录

在这里插入图片描述

xxl-job-admin:调度中心

xxl-job-core:公共依赖

xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用)

:xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;

:xxl-job-executor-sample-frameless:无框架版本;

doc :文档资料,包含数据库脚本

2.启动xxl-job

执行docker start xxl-job-admin 启动xxl-job

访问:http://192.168.101.68:8088/xxl-job-admin/

账号和密码:admin/123456

1.1.3 执行器

1.添加执行器依赖

下边配置执行器,执行器负责与调度中心通信接收调度中心发起的任务调度请求,执行器负责执行微服务中定义的任务,执行器程序由xxl-job提供,在微服务中引入下边的依赖即加入了执行器的程序:

<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId>
</dependency>

本项目在framework中定义了jzo2o-xxl-job工程,它对执行器bean执行了定义:

在这里插入图片描述

所以在需要使用xxl-job的微服务中需要引入下边的依赖,在jzo2o-foundations服务中引入下边的依赖

<dependency><groupId>com.jzo2o</groupId><artifactId>jzo2o-xxl-job</artifactId>
</dependency>

2.配置xxl-job

接下来进入nacos,配置shared-xxl-job.yaml:

在这里插入图片描述

address:调度中心的地址

appName:执行器名称,为spring.application.name表示微服务的名称(在bootstrap.yml中配置)

port:执行器端口号,通过xxl-job.port配置

在jzo2o-foundations.yaml中配置执行器的端口:

在这里插入图片描述

在jzo2o-foundations中加载shared-xxl-job.yaml:

在这里插入图片描述

3. 下边进入调度中心添加执行器

进入调度中心,进入执行器管理界面,如下图:

在这里插入图片描述

点击新增,填写执行器信息

在这里插入图片描述

AppName:执行名称,在shared-xxl-job.yaml中指定执行器名称就是微服务的应用名

名称:取一个中文名称

注册方式:自动注册,只要执行器和调度中心连通执行器会自动注册到调度中心

机器地址:自动注册时不用填写

找到应用名:jzo2o-foundations,如下图:

在这里插入图片描述

添加成功:

在这里插入图片描述

启动jzo2o-foundations,查看jzo2o-foundations的控制台:

>>>>>>>>>>> xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 11603 说明执行器启动成功

稍等片刻进入 xxl-job调度中心,进入执行器管理界面,执行器注册成功:

在这里插入图片描述

点击“查看(1)”,查看执行器的地址,如下图:

在这里插入图片描述

小结

如何配置xxl-job?

1.安装调度中心

2.配置执行器

3.在微服务中添加执行器的依赖

4.在调度配置执行器

项目为什么要用xxl-job?

xxl-job的执行器和调度中心有什么区别?

1.2 定义缓存更新任务

根据本节的目标,使用xxl-job定时更新开通区域列表的缓存

1.2.1 编写任务方法

定时执行任务就需要编写任务方法,此任务方法由执行器去调用

下边代码中demoJobHandler()就是一个任务方法,需要使用@XxlJob注解标识,所在类需要由spring去管理,所以加了@Component注解

@Component
public class SampleXxlJob {private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);/*** 1、简单任务示例(Bean模式)*/@XxlJob("demoJobHandler")//任务名字public void demoJobHandler() throws Exception {XxlJobHelper.log("XXL-JOB, Hello World.");for (int i = 0; i < 5; i++) {XxlJobHelper.log("beat at:" + i);TimeUnit.SECONDS.sleep(2);}// default success}

参考上边的代码我们编写更新开通区域列表缓存的任务方法:

先删除开通区域的缓存,再查询开通区域列表进行缓存

package com.jzo2o.foundations.handler;/*** springCache缓存同步任务**/
@Slf4j
@Component
public class SpringCacheSyncHandler {@Resourceprivate IRegionService regionService;@Resourceprivate RedisTemplate redisTemplate;/*** 已启用区域缓存更新* 每日凌晨1点执行*/@XxlJob(value = "activeRegionCacheSync")public void activeRegionCacheSync() {log.info(">>>>>>>>开始进行缓存同步,更新已启用区域");//1.清理缓存String key = RedisConstants.CacheName.JZ_CACHE + "::ACTIVE_REGIONS";redisTemplate.delete(key);//2.刷新缓存regionService.queryActiveRegionListCache();log.info(">>>>>>>>更新已启用区域完成");}}
1.2.2 配置任务

下边在调度中心配置任务

进入任务管理,新增任务:

在这里插入图片描述

填写任务信息:

在这里插入图片描述

说明:

调度类型

在这里插入图片描述

固定速度指按固定的间隔定时调度。

Cron,通过Cron表达式实现更丰富的定时调度策略。

Cron表达式是一个字符串,通过它可以定义调度策略,格式如下:

{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}

xxl-job提供图形界面去配置:

在这里插入图片描述

一些例子如下:

0 0 0 * * ? 每天0点触发

30 10 1 * * ? 每天1点10分30秒触发

0/30 * * * * ? 每30秒触发一次

* 0/10 * * * ? 每10分钟触发一次

为了方便测试这里第5秒执行一次,设置为:0/5 * * * * ?

运行模式有BEAN和GLUE,bean模式较常用就是在项目工程中编写执行器的任务代码,GLUE是将任务代码编写在调度中心

JobHandler即任务方法名,填写任务方法上边@XxlJob注解中的名称

路由策略

第一个:即每次执行任务都由第一个执行器去执行

轮询:即执行器轮番执行

分片:每次执行任务广播给每个执行器让他们同时执行任务

1.2.3 启动任务并测试

任务配置完成,下边启动任务

在这里插入图片描述

我们在任务方法上打断点跟踪,任务方法被执行,如下图:

在这里插入图片描述

尝试启用或禁用一个区域,观察redis中开通区域列表缓存是否更新

小结

项目中哪里用了xxl-job?怎么用的?

1.3 首页服务列表实现

我们先实现从数据库查询"首页服务列表",将整体功能调试通过,再实现查询缓存

下边我们先实现从数据库查询服务类型列表

1.3.1 首页服务列表实现

1.需求分析

1.界面原型

首页服务列表在门户的中心位置,下图红框中为首页服务列表区域:

在这里插入图片描述

默认展示前两个服务分类(按后台设置的排序字段进行升序排序),每个服务分类下取前4个服务项(按后台设置的排序字段进行升序排序)

一级服务分类显示的内容:服务分类的图标,服务分类的名称
在这里插入图片描述

服务分类下的服务项内容:服务项图标,服务项名称

2.接口定义

定义首页服务列表接口,查询2个一级服务分类,每个服务分类下查询4个服务项

接口名称:首页服务列表

接口路径:GET/foundations/customer/serve/firstPageServeList

在这里插入图片描述

响应示例:

{"msg": "OK","code": 200,"data": [{"serveTypeId": 0,"cityCode": "","serveTypeIcon": "","serveTypeSortNum": 0,"serveResDTOList": [{"serveItemSortNum": 0,"serveItemName": "","serveItemId": 0,"serveItemIcon": "","id": 0}],"serveTypeName": ""}]
}

定义FirstPageServeController 类提供门户界面查询类接口

package com.jzo2o.foundations.controller.consumer;@RestController("consumerServeController")
@RequestMapping("/customer/serve")
@Api(tags = "用户端 - 首页服务查询接口")
public class FirstPageServeController {@GetMapping("/firstPageServeList")
@ApiOperation("首页服务列表")
@ApiImplicitParams({@ApiImplicitParam(name = "regionId", value = "区域id", required = true, dataTypeClass = Long.class)
})
public List<ServeCategoryResDTO> serveCategory(@RequestParam("regionId") Long regionId) {return null;
}
...

3.mapper

数据来源于三张表:serve_type、serve_item、serve,区域id是非常重要的限制条件,因为要查询该区域显示在首页的服务列表

如何查询数据?可以先查询出服务类型,再根据服务类型id查询下边的服务项,伪代码如下:

package com.jzo2o.foundations.mapper;public interface ServeMapper extends BaseMapper<Serve> {/*** 首页服务列表*/List<ServeCategoryResDTO> findServeIconCategoryByRegionId(@Param("regionId") Long regionId);
}

上边的代码会导致1+n次查询数据库,这种代码要避免

我们可以一次将符合条件的数据查询出来,再通过java程序对数据进行处理,再封装为接口要求的数据格式,最后返回给前端

下边编写mapper映射文件

<select id="findServeIconCategoryByRegionId" resultMap="ServeCategoryMap">SELECTtype.id as serve_type_id,type.name as serve_type_name,type.serve_type_icon,serve.city_code,serve.id as serve_id,item.id as serve_item_id,item.name as serve_item_name,item.serve_item_icon,item.sort_num as serve_item_sort_numFROMserveinner JOIN serve_item AS item ON item.id = serve.serve_item_idinner JOIN serve_type AS type ON type.id = item.serve_type_idWHEREserve.region_id = #{regionId}AND serve.sale_status = 2ORDER BYtype.sort_num,item.sort_num
</select><!--手动的映射-->
<resultMap id="ServeCategoryMap" type="com.jzo2o.foundations.model.dto.response.ServeCategoryResDTO"><!--id映射主键字段--><id column="serve_type_id" property="serveTypeId"></id><!--result映射普通字段--><result column="serve_type_name" property="serveTypeName"></result><result column="serve_type_icon" property="serveTypeIcon"></result><result column="city_code" property="cityCode"></result><!--column 数据库中的字段名--><!--property 实体类中对应的属性 该关键字可以省略... --><!--ofType 是javaType中的单个对象类型--><collection property="serveResDTOList" ofType="com.jzo2o.foundations.model.dto.response.ServeSimpleResDTO"><id column="serve_id" property="id"></id><result column="serve_item_id" property="serveItemId"></result><result column="serve_item_name" property="serveItemName"></result><result column="serve_item_icon" property="serveItemIcon"></result><result column="serve_item_sort_num" property="serveItemSortNum"></result></collection>
</resultMap>

4.service

定义专门用于门户首页查询的service接口,用于实现查询缓存:

package com.jzo2o.foundations.service;/*** 首页查询相关功能**/
public interface HomeService {
/*** 根据区域id获取服务图标信息* @param regionId 区域id* @return 服务图标列表*/
List<ServeCategoryResDTO> queryServeIconCategoryByRegionIdCache(Long regionId);
}

定义实现类

package com.jzo2o.foundations.service.impl;/**
* 首页查询相关功能
**/
@Slf4j
@Service
public class HomeServiceImpl implements HomeService {
/**
* 根据区域id查询已开通的服务类型
* @param regionId 区域id
* @return 已开通的服务类型
*/
@Override
public List<ServeCategoryResDTO> queryServeIconCategoryByRegionIdCache(Long regionId) {//1.校验当前城市是否为启用状态Region region = regionService.getById(regionId);if (ObjectUtil.isEmpty(region) || ObjectUtil.equal(FoundationStatusEnum.DISABLE.getStatus(), region.getActiveStatus())) {return Collections.emptyList();}//2.根据城市编码查询所有的服务图标List<ServeCategoryResDTO> list = serveMapper.findServeIconCategoryByRegionId(regionId);if (ObjectUtil.isEmpty(list)) {return Collections.emptyList();}//3.服务类型取前两个,每个类型下服务项取前4个//list的截止下标int endIndex = list.size() >= 2 ? 2 : list.size();List<ServeCategoryResDTO> serveCategoryResDTOS = new ArrayList<>(list.subList(0, endIndex));serveCategoryResDTOS.forEach(v -> {List<ServeSimpleResDTO> serveResDTOList = v.getServeResDTOList();//serveResDTOList的截止下标int endIndex2 = serveResDTOList.size() >= 4 ? 4 : serveResDTOList.size();List<ServeSimpleResDTO> serveSimpleResDTOS = new ArrayList<>(serveResDTOList.subList(0, endIndex2));v.setServeResDTOList(serveSimpleResDTOS);});return serveCategoryResDTOS;
}

5.controller

在controller中调用service查询首页服务列表

package com.jzo2o.foundations.controller.consumer;@Validated
@RestController("consumerServeController")
@RequestMapping("/customer/serve")
@Api(tags = "用户端 - 首页服务查询接口")
public class FirstPageServeController {@Resourceprivate HomeService homeService;@GetMapping("/firstPageServeList")@ApiOperation("首页服务列表")@ApiImplicitParams({@ApiImplicitParam(name = "regionId", value = "区域id", required = true, dataTypeClass = Long.class)})public List<ServeCategoryResDTO> serveCategory(@RequestParam("regionId") Long regionId) {List<ServeCategoryResDTO> serveCategoryResDTOS = homeService.queryServeIconCategoryByRegionIdCache(regionId);return serveCategoryResDTOS;}
}

6.测试

重启jzo2o-foundations服务、网关服务,打开小程序,观察小程序的访问记录

在这里插入图片描述

1.3.2 首页服务列表缓存
缓存方案分析

下边是门户的缓存设计:

在这里插入图片描述

下边分析首页服务列表的缓存方案:

查询缓存:查询首页服务列表,如果缓存没有则查询数据库并缓存,如果缓存有则直接返回

注意:缓存时需要考虑缓存穿透问题。

禁用区域:删除首页服务列表缓存

定时任务:每天凌晨缓存首页服务列表。

查询缓存

下边在首页服务列表查询方法上添加Spring Cache注解实现查询缓存

为了避免缓存穿透,如果服务列表为空则向redis缓存空值,缓存时间为30分钟;不为空则进行永久缓存

在Cacheable注解中有两个属性可以指定条件进行缓存:

condition:指定一个 SpEL 表达式,用于决定是否要进行缓存。只有当条件表达式的结果为 true 时,方法的返回值才会被缓存。例如:

@Cacheable(value = "myCache", condition = "#id != null")

unless:与 condition 相反,只有当 SpEL 表达式的结果为 false 时,方法的返回值才会被缓存

例如:

@Cacheable(value = "myCache", unless = "#result.length() > 100")

#result 表示方法的返回值,如果返回值结果集的长度大于100不进行缓存

根据需求,我们需要根据方法的返回值去判断,如果结果集的长度大于0说明服务列表不空,此时缓存时间为永久缓存,否则缓存时间为30分钟

condition不支持获取方法返回的值,不能识别#result。我们使用unless实现

unless 的特点是符合条件的不缓存。设置技巧:确定要缓存的条件,取反即不缓存的条件。

当方法返回的List的size为0时缓存30分钟,避免缓存穿透,设置为:#result.size() != 0

当方法返回的List的size大于0永不过期,设置为:#result.size() == 0

代码如下:

package com.jzo2o.foundations.service.impl;/*** 首页查询相关功能**/
@Slf4j
@Service
public class HomeServiceImpl implements HomeService {@Caching(cacheable = {//result为null时,属于缓存穿透情况,缓存时间30分钟@Cacheable(value = RedisConstants.CacheName.SERVE_ICON, key = "#regionId", unless = "#result.size() != 0", cacheManager = RedisConstants.CacheManager.THIRTY_MINUTES),//查询为空处理缓存穿透//result不为null时,永久缓存@Cacheable(value = RedisConstants.CacheName.SERVE_ICON, key = "#regionId", unless = "#result.size() == 0", cacheManager = RedisConstants.CacheManager.FOREVER)}
)public List<ServeCategoryResDTO> queryServeIconCategoryByRegionIdCache(Long regionId) {//1.校验当前城市是否为启用状态Region region = regionService.getById(regionId);if (ObjectUtil.isEmpty(region) || ObjectUtil.equal(FoundationStatusEnum.DISABLE.getStatus(), region.getActiveStatus())) {return Collections.emptyList();}//2.根据城市编码查询所有的服务图标List<ServeCategoryResDTO> list = serveMapper.findServeIconCategoryByRegionId(regionId);if (ObjectUtil.isEmpty(list)) {return Collections.emptyList();}//3.服务类型取前两个,每个类型下服务项取前4个//list的截止下标int endIndex = list.size() >= 2 ? 2 : list.size();List<ServeCategoryResDTO> serveCategoryResDTOS = new ArrayList<>(list.subList(0, endIndex));serveCategoryResDTOS.forEach(v -> {List<ServeSimpleResDTO> serveResDTOList = v.getServeResDTOList();//serveResDTOList的截止下标int endIndex2 = serveResDTOList.size() >= 4 ? 4 : serveResDTOList.size();List<ServeSimpleResDTO> serveSimpleResDTOS = new ArrayList<>(serveResDTOList.subList(0, endIndex2));v.setServeResDTOList(serveSimpleResDTOS);});return serveCategoryResDTOS;}
...
查询缓存测试

启动:jzo2o-foundations服务、网关服务,打开小程序,等待首页服务列表正常显示,进入redis查看首页服务列表是否缓存

预期结果:首页服务列表正常缓存

在这里插入图片描述

定时任务更新缓存

根据缓存方案的分析,对首页服务列表进行缓存

编写定时任务代码:

/*** 已启用区域缓存更新* 每日凌晨1点执行*/
@XxlJob("activeRegionCacheSync")
public void activeRegionCacheSync() throws Exception {log.info(">>>>>>>>开始进行缓存同步,更新已启用区域");//删除缓存Boolean delete = redisTemplate.delete(RedisConstants.CacheName.JZ_CACHE + "::ACTIVE_REGIONS");//通过查询开通区域列表进行缓存List<RegionSimpleResDTO> regionSimpleResDTOS = regionService.queryActiveRegionList();//遍历区域对该区域下的服务类型进行缓存regionSimpleResDTOS.forEach(item->{//区域idLong regionId = item.getId();//删除该区域下的首页服务列表String serve_type_key = RedisConstants.CacheName.SERVE_ICON + "::" + regionId;redisTemplate.delete(serve_type_key);homeService.queryServeIconCategoryByRegionIdCache(regionId);//todo 删除该区域下的服务类型列表缓存});
}
定时任务更新缓存测试

先将首页服务列表的缓存手动删除。

重启foundations服务,在上边代码中打断点,保证定时任务成功执行。

预期结果:对每个运营区域的首页服务列表进行缓存

示例:跟踪断点执行

在这里插入图片描述

编码规范

门户信息查询类接口统一在FirstPageServeController类中定义,service统一写在HomeService下。

首先实现业务接口的功能,测试通过后再去实现缓存。

禁用区域时删除缓存

找到禁用区域代码 ,添加删除首页服务列表缓存的代码,如下:


@Service
public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements IRegionService {
...@Override@Caching(evict = {@CacheEvict(value = RedisConstants.CacheName.JZ_CACHE, key = "'ACTIVE_REGIONS'"),@CacheEvict(value = RedisConstants.CacheName.SERVE_ICON, key = "#id")})public void deactivate(Long id) {

测试:禁用一个区域观察redis是否删除该区域的首页服务列表缓存

小结

项目中有做缓存吗?考虑缓存穿透问题了吗?怎么实现的?

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

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

相关文章

SuperdEye:一款基于纯Go实现的间接系统调用执行工具

关于SuperdEye SuperdEye是一款基于纯Go实现的间接系统调用执行工具&#xff0c;该工具是TartarusGate 的修订版&#xff0c;可以利用Go来实现TartarusGate 方法进行间接系统调用。 该工具的目标是为了扫描挂钩的NTDLL并检索Syscall编号&#xff0c;然后使用它来执行间接系统调…

Python+ tkinter实现小学整数乘法和除法竖式演算式

Python tkinter实现小学整数乘法和除法竖式演算式 整数的乘法与除法是小学数学中的重要内容&#xff0c;它们是数学运算中的基础部分。 本文将使用python 和Python 的标准 GUI&#xff08;图形用户界面&#xff09;包tkinter&#xff0c;实现整数乘法与除法的竖式演示。供有兴趣…

线程池遇到未处理的异常会崩溃吗?

线程池中的 execute 和 submit 方法详解 目录 引言execute 方法 使用示例代码 submit 方法 2.1 提交 Callable 任务2.2 提交 Runnable 任务 遇到未处理异常 3.1 execute 方法遇到未处理异常3.2 submit 方法遇到未处理异常 小结 引言 在多线程编程中&#xff0c;线程池是提高性…

MongoDB基本操作

一、实验目的 1. 熟悉MongoDB的基本操作&#xff0c;包括CRUD&#xff08;增加、读取、更新、删除&#xff09;。 2. 理解MongoDB的文档型数据库特性和Shell的使用。 3. 培养学生通过命令行操作数据库的能力。 4. 强化数据库操作的实际应用能力。 二、实验环境准备 1.…

【银河麒麟高级服务器操作系统】业务访问慢网卡丢包现象分析及处理过程

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;product.kylinos.cn 开发者专区&#xff1a;developer.kylinos.cn 文档中心&#xff1a;document.kylinos.cn 交流论坛&#xff1a;forum.kylinos.cn 服务器环境以及配置 【内核版本…

Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正

Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正 1 添加依赖2 测试代码3 测试结果 在OpenCV中&#xff0c;仿射变换&#xff08;Affine Transformation&#xff09;和透视变换&#xff08;Perspective Transformation&#xff09;是两种常用的图像几何变换方法。 变换方…

【LeetCode100】--- 寻找重复数

题目传送门 方法一&#xff1a;暴力解法&#xff08;超时&#xff09; 算法原理 双重循环&#xff0c;每次固定一个数&#xff0c;再遍历别的数。比较这两个数是否相等&#xff0c; 若相等则返回这个数。就是重复数。 复杂度分析 时间复杂度&#xff1a;O&#xff08;N方&…

RabbitMQ---TTL与死信

&#xff08;一&#xff09;TTL 1.TTL概念 TTL又叫过期时间 RabbitMQ可以对队列和消息设置TTL&#xff0c;当消息到达过期时间还没有被消费时就会自动删除 注&#xff1a;这里我们说的对队列设置TTL,是对队列上的消息设置TTL并不是对队列本身&#xff0c;不是说队列过期时间…

mysql查看binlog日志

mysql 配置、查看binlog日志&#xff1a; 示例为MySQL8.0 1、 检查binlog开启状态 SHOW VARIABLES LIKE ‘log_bin’; 如果未开启&#xff0c;修改配置my.ini 开启日志 安装目录配置my.ini(mysql8在data目录) log-binmysql-bin&#xff08;开启日志并指定日志前缀&#xff…

【QT】 控件 -- 按钮类(Button)

&#x1f525; 目录 1. 前言 2. Push Button 按钮 1、带有图标的按钮 -- 纯代码实现2、带有快捷键的按钮 -- 图形化&代码实现 3、按钮的重复触发 3. Radio Button 按钮 **1. click、press、release、toggled 的区别** **2. 单选框分组** 4. Check Box 复选 5. Tool Butto…

postman请求参数化

postman界面介绍 一、使用环境变量(Environment Variables)进行参数化 1、在请求中使用环境变量 在请求的url、请求头(Headers)、请求体(Body)等部分都可以使用环境变量。 URL 部分示例 点击 Postman 界面右上角的 “眼睛” 图标(Environment Quick Look)打开环境管理…

在 Babylon.js 中使用 Gizmo:交互式 3D 操作工具

在 3D 应用程序中&#xff0c;交互式操作对象&#xff08;如平移、旋转、缩放&#xff09;是一个常见的需求。Babylon.js 提供了一个强大的工具——Gizmo&#xff0c;用于在 3D 场景中实现这些功能。本文将介绍如何在 Babylon.js 中使用 Gizmo&#xff0c;并展示如何通过代码实…

虚幻商城 Fab 免费资产自动化入库

文章目录 一、背景二、实现效果展示三、实现自动化入库一、背景 上一次写了个这篇文章 虚幻商城 Quixel 免费资产一键入库,根据这个构想,便决定将范围扩大,使 Fab 商城的所有的免费资产自动化入库,是所有!所有! 上一篇文章是根据下图这部分资产一键入库: 而这篇文章则…

Ubuntu 22.04.5 修改IP

Ubuntu22.04.5使用的是netplan管理网络&#xff0c;因此需要在文件夹/etc/netplan下的01-network-manager-all.yaml中修改&#xff0c;需要权限&#xff0c;使用sudo vim或者其他编辑器&#xff0c;修改后的内容如下&#xff1a; # Let NetworkManager manage all devices on …

通过学习更多样化的生成数据进行更广泛的数据分发来改进实例分割

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 本次使用的英文整理的一些记录&#xff0c;练习一下为后续SCI发表论文打好基础 Improving Instance Segmentation by Learning Wider Data Distribution with More Diverse Generative Data Abstract In…

写作利器:如何用 PicGo + GitHub 图床提高创作效率

你好呀&#xff0c;欢迎来到 Dong雨 的技术小栈 &#x1f331; 在这里&#xff0c;我们一同探索代码的奥秘&#xff0c;感受技术的魅力 ✨。 &#x1f449; 我的小世界&#xff1a;Dong雨 &#x1f4cc; 分享我的学习旅程 &#x1f6e0;️ 提供贴心的实用工具 &#x1f4a1; 记…

通过Ukey或者OTP动态口令实现windows安全登录

通过 安当SLA&#xff08;System Login Agent&#xff09;实现Windows安全登录认证&#xff0c;是一种基于双因素认证&#xff08;2FA&#xff09;的解决方案&#xff0c;旨在提升 Windows 系统的登录安全性。以下是详细的实现方法和步骤&#xff1a; 1. 安当SLA的核心功能 安…

基于Python的多元医疗知识图谱构建与应用研究(上)

一、引言 1.1 研究背景与意义 在当今数智化时代,医疗数据呈爆发式增长,如何高效管理和利用这些数据,成为提升医疗服务质量的关键。传统医疗数据管理方式存在数据孤岛、信息整合困难等问题,难以满足现代医疗对精准诊断和个性化治疗的需求。知识图谱作为一种知识表示和管理…

疑难Tips:解决 SQL*Plus 中工具插入中文数据到Oracle数据库报错及乱码问题

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] 原文地址&#xff1a;疑难Tips&#xff1a;解决 SQL*Plus 中工具插入中文数据到Oracle数据库报错及乱码问题在SQL*Plus执行插入语句中含有中文时&#xff0c;出现ORA-01756错误和乱码。这两个问题…

Mac 上如何安装Mysql? 如何配置 Mysql?以及如何开启并使用MySQL

前言&#xff1a; 有许多开发的小伙伴&#xff0c;使用的是mac&#xff0c;那么在mac上如何安装&#xff0c;配置Mysql&#xff0c;以及使用Mysql了&#xff0c;今天来一个系统的教程。 安装Mysql 使用mysql前&#xff0c;我们需要先下载mysql&#xff0c;并按照以下几个步骤…