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

基于京东:HotKey实现自动缓存热点Key!!!

一.引言

某些热点数据,我们提前如果能够预判到的话,可以提前人工给数据加缓存,也就是缓存预热,将其缓存在本地或者Redis中,提高访问性能同时,减低数据库压力,也减轻后端服务的压力。但是,有些时候,我们无法预料到哪些数据是热点,比如一个冷门数据,突然变成一个热点数据,没来得及缓存,突然被大量访问,系统不就故障了吗!?

因此,我们就需要帮助我们快速发现热点Key,并且自动缓存哪就不解决太多问题了嘛!!!因此京东的这个HotKey中间件就来了。

二.介绍

官网:JDHotKey

介绍:

对任意突发性的无法预先感知的热点数据,包括并不限于热点数据(如突发大量请求同一个商品)、热用户(如恶意爬虫刷子)、热接口(突发海量请求同一个接口)等,进行毫秒级精准探测到。然后对这些热数据、热用户等,推送到所有服务端JVM内存中,以大幅减轻对后端数据存储层的冲击,并可以由使用者决定如何分配、使用这些热key(譬如对热商品做本地缓存、对热用户进行拒绝访问、对热接口进行熔断或返回默认值)。这些热数据在整个服务端集群内保持一致性,并且业务隔离,worker端性能强悍。

京东APP后台热数据探测框架,历经多次高压压测和2020年京东618、双11大促考验。

在上线运行的这段时间内,每天探测的key数量数十亿计,精准捕获了大量爬虫、刷子用户,另准确探测大量热门商品并毫秒级推送到各个服务端内存,大幅降低了热数据对数据层的查询压力,提升了应用性能。

 

核心组件
它的主要核心组件如下:
1) Etcd 集群
Etcd 作为一个高性能的配置中心,可以以极小的资源占用,提供高效的监听订阅服务。主要用于存放规则配置,各 worker的 ip 地址,以及探测出的热 key、手工添加的热 key 等。Etcd 常用于配置中心和注册中心
2) client端iar包
就是在服务中添加的引用jar,引入后,就可以便捷地去判断某 key 是否热 key。同时,该 jar 完成了 key 上报、监听 Etcd
里的 rule 变化、worker 信息变化、热 key 变化,对热 key 进行本地 Caffeine 缓存等。
3) worker端集群
worker 端是一个独立部署的 Java 程序,启动后会连接 Etcd,并定期上报自己的 ip 信息,供 client 端获取地址并进行长连
接。之后,主要就是对各个 client 发来的待测 key 进行 累加计算,当达到 Etcd 里设定的 rule 阈值后,将热 key 推送到各
个client.
4) dashboard 控制台
控制台是一个带可视化界面的 Java 程序,也是连接到 Etcd,之后在控制台设置各个 APP 的 key 规则,譬如 2 秒出现,20次算热 key。然后当 worker 探测出来热 key 后,会将 key 发往 etcd,dashboard 也会监听热 key 信息,进行入库保存记录。同时,dashboard 也可以手工添加、删除热 key,供各个 client 端监听。


更详细的内容,可见京东技术团队 官方的文章,最具可信度。

三.安装

1. Etcd 安装:

在etcd下载页面下载对应操作系统的etcd,https://github.com/etcd-io/etcd/releases 使用3.4.x以上。 

下载后解压压缩包,会得到3个脚本

  • etcd:etcd 服务本身
  • etcdctl:客户端,用于操作 etcd,比如读写数据
  • etcdutl:备份恢复工具

输入etcd 启动!!! 

执行 etcd 脚本后,可以启动 etcd 服务,服务默认占用 2379 和 2380 端口,作用分别如下:

  • ·2379:提供 HTTP API服务,和 etcdct 交互
  • ·2380:集群中节点间通讯 

2. worker安装

从 hotkey 官方仓库 下载源码 ->>>> 下载地址

注意:::    JDK 的版本必须小于 17!否则会报找不到类,因为有些类jdk17已经弃用了!!!
的错误!
项目导入 IDEA后,打开 worker 模块。worker 是一个 Spring Boot 项目,启动前需要先修改 applicaiton.yml 中的配置。
比如端口配置( 8111) 

修改完配置后,直接点击WorkerApplication 启动即可,
如下图,此时 worker 就已经正常启动,并且连接上 Etcd 了:

3. 启动 hotkey 控制台

接着打开 dashboard 项目,执行 resource 目录下的 db.sql文件,创建 dashboard 所需的库表。hotkey 依赖 MySQL
储用户账号信息、热点阈值规则等。
在执行脚本前,记得先配置好 MySQL 连接,并且在 SQL 脚本文件中创建和指定数据库
执行脚本过程如图

修改端口及数据库配置 

server:port: 8182
spring:datasource:username: ${MYSQL_USER:root}password: ${MYSQL_PASS:1234}url: jdbc:mysql://${MYSQL_HOST:localhost}:3306/hotkey_db?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC&useTimezone=true&serverTimezone=GMTdriver-class-name: com.mysql.cj.jdbc.Driver
etcd:server: ${etcdServer:http://127.0.0.1:2379}

dashboard 也是一个 SpringBoot 项目,直接在 IDEA 内执行 DashboardApplication 启动即可
访问 http://127.0.0.1:8182,端口就是你自己配置的 即可看到界面: 

初始Sql的时候,会有一个默认账号: admin 密码: 123456 (加密了的) 登录:

初次使用时需要先添加 APP。建议先在用户管理菜单中,添加一个新用户,设置昵称为 APP 名称、并填写所属 APP,如
GCXF-App,密码此处就设置为 123456。之后就可以登录这个新建的用户来给应用设置规则了(当然也可以使用 admin 账
户添加),而且系统会自动创建一个 APP。

随后,在规则配置中,选择对应的 APP,新增对应的热点探测规则:

我这里的意思就是判断poem_开头的key,如果5秒内访问 如果5秒访问 10 次,就会被推送到jvm 内存中,将这个热 key 缓存3 分钟。


对应的规则配置如下:

[{"key":"poem_","prefix":true,"interval":5,"threshold":10,"duration":180,"desc":"搜索热点key"}
]

  • key:(*代表任意以key为前缀) 只要到时候client端上报这样子的key于这边相互匹配就可以完成统计
  • prefix:是否前缀,  
  • interval:间隔时间(秒),
  • threshold:阈值, 
  • duration-缓存时间(秒):默认60
  • desc:描述

 4. 引入 hotkey client

有2 种引入 hotkey client 的方式:
1.手动源码打包
2.通过 Maven 远程仓库 引入
由于 Maven 远程仓库的包引用量过少,而且不具备官方权威性,所以更推荐通过 hotkey 源码手动打包。
所以选择方式 1,手动将 hotkey 源码中的 client 模块通过 Maven 打成 jar 包:

在我们引入的项目中新键一个lib文件,然后放入client的jar包

 

引入依赖;

    <!-- hotkey --><dependency><artifactId>hotkey-client</artifactId><groupId>com.jd.platform.hotkey</groupId><version>0.0.4-SNAPSHOT</version><scope>system</scope><systemPath>${project.basedir}/lib/hotkey-client-0.0.4-SNAPSHOT.jar</systemPath></dependency>

 引入依赖后,在代码中编写初始化 client 的配置类,会读取配置文件并执行初始化逻辑

@Configuration
@ConfigurationProperties(prefix = "hotkey")
@Data
public class HotKeyConfig {/*** Etcd 服务器完整地址*/private String etcdServer = "http://127.0.0.1:2379";/*** 应用名称*/private String appName = "app";/*** 本地缓存最大数量*/private int caffeineSize = 10000;/*** 批量推送 key 的间隔时间*/private long pushPeriod = 1000L;/*** 初始化 hotkey*/@Beanpublic void initHotkey() {ClientStarter.Builder builder = new ClientStarter.Builder();ClientStarter starter = builder.setAppName(appName).setCaffeineSize(caffeineSize).setPushPeriod(pushPeriod).setEtcdServer(etcdServer).build();starter.startPipeline();}
}

注:这里spring-boot不要太高,因为不允许是void的返回值的(也可以用提供的接口来解决),所有干脆调到3.0.2下就可以了

pom.xml


# 热 key 探测
hotkey:app-name: GCXF-Appcaffeine-size: 10000push-period: 1000etcd-server: http://localhost:2379app-name: GCXF-App: 这是一个键值对,其中app-name是键,GCXF-App是值。这表示应用程序的名称被设置为GCXF-App。这个值可能用于标识这个配置所属的应用程序。caffeine-size: 10000: 这也是一个键值对,其中caffeine-size是键,10000是值。这个值可能代表某种缓存(可能是指Caffeine缓存库)的大小设置,单位可能是条目数、字节或其他,具体取决于上下文。Caffeine是一个高性能的Java缓存库。push-period: 1000: 这是一个表示时间间隔的键值对,意味着这个操作每秒去Push一次 上报一次。etcd-server: http://localhost:2379: 这个值指定了etcd服务器的地址和端口,客户端可以通过这个地址与etcd服务器进行通信。

这里的App-name与你先去在etcd中配置app必须一致

启动:可以看到有一个客户端链接了

OK,我们就可以使用了

四.使用

主要有如下4个方法可供使用

  1. boolean JdHotKeyStore.isHotKey(String key)
  2. Object JdHotKeyStore.get(String key)
  3. void JdHotKeyStore.smartSet(String key, Object value)
  4. Object JdHotKeyStore.getValue(String key)

1 boolean isHotKey(String key) ,该方法会返回该key是否是热key,如果是返回true,如果不是返回false,并且会将key上报到探测集群进行数量计算。该方法通常用于判断只需要判断key是否热、不需要缓存value的场景,如刷子用户、接口访问频率等。

2 Object get(String key),该方法返回该key本地缓存的value值,可用于判断是热key后,再去获取本地缓存的value值,通常用于redis热key缓存

3 void smartSet(String key, Object value),方法给热key赋值value,如果是热key,该方法才会赋值,非热key,什么也不做

4 Object getValue(String key),该方法是一个整合方法,相当于isHotKey和get两个方法的整合,该方法直接返回本地缓存的value。 如果是热key,则存在两种情况,1是返回value,2是返回null。返回null是因为尚未给它set真正的value,返回非null说明已经调用过set方法了,本地缓存value有值了。 如果不是热key,则返回null,并且将key上报到探测集群进行数量探测。

 官网推荐的最佳实践:

1 判断用户是否是刷子

if (JdHotKeyStore.isHotKey(“pin__” + thePin)) {// 进行限流
}

2 判断商品id是否是热点

Object skuInfo = JdHotKeyStore.getValue("skuId__" + skuId);
if(skuInfo == null) {JdHotKeyStore.smartSet("skuId__" + skuId, theSkuInfo);
} else {// 使用缓存好的 value 即可
}

或者这样:

if (JdHotKeyStore.isHotKey(key)) {//注意是get,不是getValue。getValue会获取并上报,get是纯粹的本地获取Object skuInfo = JdHotKeyStore.get("skuId__" + skuId);if(skuInfo == null) {JdHotKeyStore.smartSet("skuId__" + skuId, theSkuInfo);} else {//使用缓存好的value即可}
}

代码测试:

  @Autowiredprivate HotKeyPoemMapper hotKeyPoemMapper;@Autowiredprivate PoemNameMapper poemNameMapper;private RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.184.128:9200")));/*** 查询所有古诗** @param name* @return*/@Overridepublic PoemNameVO selectPoemByName(String name) {String key = "poem_" + name;// 判断是否是热搜if (JdHotKeyStore.isHotKey(key)) {// 获取缓存Object poemNameVO = JdHotKeyStore.get(key);if (poemNameVO != null) {return (PoemNameVO) poemNameVO;}}PoemName poenNmae = null;poenNmae = poemNameMapper.selectPoemByName(name);if (poenNmae == null) {throw new PoenException(MessageContast.POEM_ERROR);}PoemNameVO poemNameVO = new PoemNameVO();//获取注释List<poemExplain> poemExplains = poemNameMapper.selectBypoenID(Long.valueOf(poenNmae.getId()));//判断是否有该收藏古诗 1返回true null 返回faslePoemNameVO poemNameVO1 = poemNameMapper.selectCollectByHeader(name);if (poemNameVO1 == null) {poemNameVO.setTrue(false);} else {poemNameVO.setTrue(true);}List<String> list = new ArrayList<>();//获取全文集合String[] split = poenNmae.getAllpoem().split("。");for (String s : split) {list.add(s);}poemNameVO.setAllpoem(list);list = new ArrayList<>();//获取背景集合String[] split1 = poenNmae.getPoemDrop().split("。");for (String s : split1) {list.add(s);}poemNameVO.setPoemDrops(list);//复制传参BeanUtils.copyProperties(poenNmae, poemNameVO);poemNameVO.setPoemExplain(poemExplains);if(JdHotKeyStore.isHotKey(key)){// 设置缓存JdHotKeyStore.smartSet(key, poemNameVO);//并且给热点key累加排行poemNameMapper.sumTheHotKey(name);}return poemNameVO;}

因为上面我们配置了5秒内访问10次就会变成热点Key,之后我们就会把这个数据存储到本地缓存中,下次访问的时候就会直接从本地缓存中去读取了,并不会在去查询数据库了。 

我们测试一下

通过接口5秒内访问了10次后 

然后可以看间 事实热点已经有了

 当我们再次访问,就不会查询数据库了,都是通过本地缓存来查询,可以感觉到非常块!

源码;

1) 热 key 会自动续期吗?否则可能出现缓存雪崩的问题?

  public static boolean isHotKey(String key) {try {if (!inRule(key)) {return false;} else {boolean isHot = isHot(key);if (!isHot) {HotKeyPusher.push(key, (KeyType)null);} else {ValueModel valueModel = getValueSimple(key);if (isNearExpire(valueModel)) {HotKeyPusher.push(key, (KeyType)null);}}KeyHandlerFactory.getCounter().collect(new KeyHotModel(key, isHot));return isHot;}} catch (Exception var3) {return false;}}public static Object get(String key) {ValueModel value = getValueSimple(key);if (value == null) {return null;} else {Object object = value.getValue();return object instanceof Integer && Constant.MAGIC_NUMBER == (Integer)object ? null : object;}}

分析:

然后看下源码,就知道为什么了。源码中的逻辑是,首先会校验这个key是否在规则中,如果不是当然返回fasle,然后才判断是否是热点key,如果已经是热 key ,返回缓存值但是不会再 push,离过期还有2秒内的时候,会再次 push,这样这个 key 可能被继续设置为热 key。

也就是说,如果一个 key 持续被访问,很有可能在过期前一直被设置为热点,减少了出现雪崩问题的可能性。

2.)能够和 redis 分布式缓存结合
热 key 探测 = 热 key 发现 +本地缓存。可以只利用热 key 的判断方法,来给我们判断哪些是热Key,不利用热 key 的存储方法即可,通过换成redis存储也是可以

方法:

1.不是热 key,就查数据库。对于热 key,写缓存时,再判断一下是否为热 key,是热 key 才设置 Redis 分布式缓存。后续的热 key 就可以从分布式缓存中获取值。(缓存存储的技术或者位置变了)
2.利用热 key 探测的本地缓存,将原本査数据库的逻辑改为査 Redis,Redis 查不到才查询数据库,形成多级缓存。
 

 3.) 如何更新本地缓存
需要有一个入口让缓存失效,进行人工干预。hotkey 提供了 JdHotKeystore.remove()方法,可以手动删除本地缓存并移除热点 key。
以利用控制台手动删除:

不过一般情况下,热点信息一般都是不太会变更的数据,过期时间设置短一点即可。

相关文章:

基于京东:HotKey实现自动缓存热点Key!!!

一.引言 某些热点数据&#xff0c;我们提前如果能够预判到的话&#xff0c;可以提前人工给数据加缓存&#xff0c;也就是缓存预热&#xff0c;将其缓存在本地或者Redis中&#xff0c;提高访问性能同时&#xff0c;减低数据库压力&#xff0c;也减轻后端服务的压力。但是&#…...

★ 算法OJ题 ★ 二分查找算法

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;塞尔达将和大家一起做几道二分查找算法算法题 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 算法专栏&#xff1a;★ 优选算法100天 ★_椎名澄嵐的博客-CSDN博客…...

RTSP RTP RTCP SDP基础知识

理论 流&#xff08;Streaming &#xff09; 是近年在 Internet 上出现的新概念&#xff0c;其定义非常广泛&#xff0c;主要是指通过网络传输多媒体数据的技术总称。 流式传输分为两种 顺序流式传输 (Progressive Streaming) 实时流式传输 (Real time Streaming) ​​​​​…...

静态变量、变量作用域、命名空间

静态变量 静态变量一般位于程序全局data区&#xff0c;只是编程语言根据它所在的scope做语言级别访问限制。 静态变量和全局变量 可以在C语言一个函数中定义static变量&#xff0c;并比较和全局变量的地址差异。 C系语言使用static关键字标示静态变量。 PHP使用大写的STATIC关键…...

Android笔记(二十四)基于Compose组件的MVVM模式和MVI模式的实现

仔细研究了一下MVI(Model-View-Intent)模式&#xff0c;发现它和MVVM模式非常的相识。在采用Android JetPack Compose组件下&#xff0c;MVI模式的实现和MVVM模式的实现非常的类似&#xff0c;都需要借助ViewModel实现业务逻辑和视图数据和状态的传递。在这篇文章中&#xff0c…...

MySQL 是否支持 XML

MySQL 是否支持 XML&#xff1a;概述与应用 虽然 MySQL 主要以处理关系型数据为主&#xff0c;但它也提供了对 XML 数据的支持。XML&#xff08;可扩展标记语言&#xff09;是一种用于数据传输和存储的通用格式。在许多应用场景中&#xff0c;XML 被广泛用于数据交换、配置文件…...

pikachu靶场总结(四)

九、越权漏洞 1.概述 如果使用A用户的权限去操作B用户的数据&#xff0c;A的权限小于B的权限&#xff0c;如果能够成功操作&#xff0c;则称之为越权操作。 越权漏洞形成的原因是后台使用了 不合理的权限校验规则导致的。 一般越权漏洞容易出现在权限页面&#xff08;需要登…...

24.3 基于文件的服务发现模式

本节重点介绍 : 基于文件的服务发现提供了一种配置静态目标的更通用的方法可以摆脱对特定服务发现源的依赖通常的做法是调用内部CMDB的接口获取target数据&#xff0c;打上标签&#xff0c;生成json文件发给prometheus采集 基于文件的服务发现模式 解决的问题 之前手动配置…...

【Java】面向UDP接口的网络编程

【Java】面向UDP接口的网络编程 一. 基本通信模型二. APIDatagramSocketDatagramPacket 三. 回显服务器/客户端示例服务器客户端总结 一. 基本通信模型 UDP协议是面向数据报的&#xff0c;因此此处要构建数据报(Datagram)在进行发送。 二. API DatagramSocket DatagramSocke…...

SRS服务器搭建

1、配置 listen 1935; max_connections 1000; #srs_log_tank file; #srs_log_file ./objs/srs.log; daemon on; http_api { enabled on; listen 1985; } http_server { enabled on; listen 808…...

iMazing只能苹果电脑吗 Win和Mac上的iMazing功能有区别吗

在当今数字时代&#xff0c;管理和备份手机数据变得越来越重要。无论是转移照片、备份短信&#xff0c;还是管理应用程序&#xff0c;一个强大的工具可以大大简化这些操作。iMazing作为一款备受好评的iOS设备管理软件&#xff0c;已经成为许多用户的选择。但是&#xff0c;许多…...

ChatGPT可以分析股票吗?

结合国庆前大A股市的小波牛市以及今天的股市表现&#xff0c;我从多个角度为你提供一些分析和建议&#xff1a; 一、国庆前的小波牛市分析 国庆前&#xff0c;大A股市出现了一波小幅上涨&#xff0c;市场呈现出一些积极的信号&#xff1a; 政策面利好&#xff1a;政府出台了…...

Dockerfile搭建镜像

Dockerfile搭建镜像的优势与区别 引言 在现代软件开发与运维中&#xff0c;容器化技术日益普及&#xff0c;而Docker作为最流行的容器化平台之一&#xff0c;通过Dockerfile提供了一种灵活、自动化的方式来构建Docker镜像。Dockerfile使得镜像的构建过程可重复、可版本化&…...

Kubernetes-Kind篇-01-kind搭建测试集群

1、Kind 介绍 官方文档地址&#xff1a;https://kind.sigs.k8s.io/ github仓库地址&#xff1a;https://github.com/kubernetes-sigs/kind 国内镜像仓库地址&#xff1a;https://gitcode.com/gh_mirrors/ki/kind/overview kind 是一种使用 Docker 容器 nodes 运行本地 Kubern…...

在UniApp中高效处理大量文件请求的策略

在开发跨平台应用时&#xff0c;尤其是在使用UniApp这样的框架时&#xff0c;我们可能会遇到需要同时请求多个文件的情况。然而&#xff0c;不加节制地同时发起大量请求可能会带来严重的性能问题&#xff0c;如界面卡顿、内存溢出、网络带宽饱和等。本文将探讨如何在UniApp中高…...

docker compose入门4—常用命令

在使用 Docker Compose 管理多容器应用时&#xff0c;常见的命令帮助我们高效地管理容器的生命周期、服务、日志等。以下是一些常用的 Docker Compose 命令及其详细讲解&#xff1a; 1. docker-compose up 这个命令用于启动定义在 docker-compose.yml 文件中的服务。 用法&am…...

wps文本框文字居中对齐

直接点对齐里的水平居中&#xff0c;垂直居中是将文本框水平垂直居中&#xff0c;文字不会居中 将文本框里的文字居中&#xff1a; 垂直居中&#xff1a; 水平居中&#xff1a;...

注册信息页面

知识点&#xff1a; &#xff01;&#xff0b;Enter 直接生成前端基本框架 1.<h1></h1> (2,3,4,5) 表示各级标题 2.<form></form> 表单建立 3.<input type" "></input> 表格&#xff08;表单嵌套表格&#xff09; type属…...

详解Java中的BIO、NIO、AIO

1、 详解Java中的BIO、AIO、NIO 1.1、引言 IO流是Java中比较难理解的一个知识点&#xff0c;但是IO流在实际的开发场景中经常会使用到&#xff0c;比如Dubbo底层就是NIO进行通讯。本文将介绍Java发展过程中出现的三种IO&#xff1a;BIO、NIO以及AIO&#xff0c;重点介绍NIO。…...

CAN和CANFD如何转换和通信

随着科技的发展&#xff0c;汽车电子和工业领域中CAN通信需要承载数据量也越来越大&#xff0c;传统CAN通信有了向CANFD通信过渡的倾向。在实现过渡的过程中可能会出现自己设备是CAN通信&#xff0c;客户设备是CANFD通信的情况&#xff0c;或者自己设备是CANFD通信&#xff0c;…...

QDateTimeEdit Class

Header:#include qmake:QT += widgets Inherits:QAbstractSpinBox Inherited By:QDateEdit and QTimeEdit Public Types enum Section {NoSection, AmPmSection, MSecSection, SecondSection, MinuteSection, …, YearSection } flags SectionsProperties calendarPopu…...

Windows环境安装CentOS7

【注意】安装CentOS需要先安装Vmware虚拟机 【下载前准备】 一、下载CentOS 7镜像文件阿里云镜像开源&#xff0c;点击跳转 二、安装VMware&#xff08;17&#xff09;&#xff1a; a. 官网&#xff0c;点击跳转 b. 许可证&#xff1a;JU090-6039P-08409-8J0QH-2YR7F 安装V…...

用docker启动mysql步骤

以下是在 Docker 中启动 MySQL 的详细步骤&#xff1a; **一、拉取 MySQL 镜像 ** 1. 打开终端&#xff0c;确保 Docker 服务正在运行。可以使用以下命令检查 Docker 服务状态&#xff1a; sudo systemctl status docker 2. 使用以下命令拉取 MySQL 官方镜像&#xff1a; d…...

[Linux] Linux 初识进程地址空间 (进程地址空间第一弹)

标题&#xff1a;[Linux] Linux初识进程地址空间 个人主页水墨不写bug &#xff08;图片来源于AI&#xff09; 目录 一、什么是进程地址空间 二、为什么父子进程相同地址的变量的值不同 三、初识虚拟地址、页表 一、什么是进程地址空间 其实&#xff0c;在很久之前&#xf…...

力扣21~25题

21题&#xff08;简单&#xff09;&#xff1a; 分析&#xff1a; 按要求照做就好了&#xff0c;这种链表基本操作适合用c写&#xff0c;python用起来真的很奇怪 python代码&#xff1a; # Definition for singly-linked list. # class ListNode: # def __init__(self, v…...

04. prometheus 监控 Windows 服务器

prometheus 监控 Windows 服务器 1. 下载安装 Windows_exporter 安装包下载&#xff1a;https://github.com/prometheus-community/windows_exporter/releases 下载 msi 版本&#xff0c;上传至要监控的 Windows 服务器&#xff0c;双击安装即可&#xff0c;exporter 会自动…...

【机器学习】——决策树以及随机森林

文章目录 1. 决策树的基本概念与结构1.1 决策树的构建过程 2. 决策树的划分标准2.1 信息增益&#xff08;Information Gain&#xff09;2.2 信息增益比&#xff08;Information Gain Ratio&#xff09;2.3 基尼指数&#xff08;Gini Index&#xff09;2.4 均方误差&#xff08;…...

怎么选择合适的数据恢复软件?适用于 Windows 的数据恢复软件对比

针对 Windows 的领先数据恢复软件的全面回顾&#xff1a; 丢失重要数据对任何 Windows 用户来说都是一场噩梦。从意外删除到系统崩溃&#xff0c;数据丢失是一个非常普遍的问题。值得庆幸的是&#xff0c;有强大的数据恢复工具可以帮助找回丢失的文件。这篇评论深入探讨了适用于…...

CI/CD 和 DevOps 工具概述:Jenkins 、Docker 的概述、工作流程、对比

随着软件开发的复杂性不断增加&#xff0c;持续集成&#xff08;CI&#xff09;、持续交付&#xff08;CD&#xff09;和运维&#xff08;Ops&#xff09;的概念逐渐成为现代软件开发流程中的核心组成部分。这些概念促进了开发团队与运维团队之间的协作&#xff0c;提升了软件的…...

基于SpringBoot+Vue+uniapp的高校教务管理小程序系统设计和实现

2. 详细视频演示 文章底部名片&#xff0c;联系我获取更详细的演示视频 3. 论文参考 4. 项目运行截图 代码运行&#xff0c;效果展示图 代码运行&#xff0c;效果展示图 代码运行&#xff0c;效果展示图 代码运行&#xff0c;效果展示图 代码运行&#xff0c;效果展示图 5. 技…...