Apache atlas 元数据管理治理平台使用和架构
1、前言
Apache Atlas 是托管于 Apache 旗下的一款元数据管理和治理的产品,目前在大数据领域应用颇为广泛,可以很好的帮助企业管理数据资产,并对这些资产进行分类和治理,为数据分析,数据治理提供高质量的元数据信息。
随着企业业务量的逐渐膨胀,数据日益增多,不同业务线的数据可能在多种类型的数据库中存储,最终汇集到企业的数据仓库中进行整合分析,这个时候如果想要追踪数据来源,理清数据之间的关系将会是一件异常头疼的事情,倘若某个环节出了问题,追溯的成本将是巨大的,于是 Atlas 在这种背景下应运而生了,通过它,我们可以非常方便的管理元数据,并且可以追溯表级别,列级别之间的关系(血缘关系),为企业的数据资产提供强有力的支撑和保障。Atlas 支持从 HBase 、Hive、Sqoop、Storm、Kafka 中提取和管理元数据,同时也可以通过 Rest Api 的方式自行定义元数据模型,生成元数据。
本文我们着重介绍一下 Atlas 的相关概念,帮助大家更好的理解 Atlas,同时详细讲解如何通过 Rest Api 的方式自定义数据模型,生成血缘关系,以便开发自己的个性化需求。
2、Atlas 原理及相关概念
元数据
元数据其实就是描述数据的数据,比如表,字段,视图等,每个业务系统可能都会自己定义表,字段,视图,这些数据从哪来到往哪去,数据之间是否存在关联,和其他系统的数据是否存在重复和矛盾字段,这些就是元数据管理要解决的问题,也是 Atlas 要解决的问题。
运行原理
Atlas 的原理其实并不难理解,主要是通过内部提供的脚本读取数仓中的数据库结构,生成数据模型,存储到 Atlas的 Hbase 中,同时通过 hook 的方式监听数仓中的数据变化,分析执行的 sql 语句,从而生成表与表,列与列的血缘关系依赖,在前台展示给用户查看。
数仓支持
Atlas 对 Hive 支持最好,我们都知道,Hive 是依赖于 Hadoop 的,数据存储在 HDFS 中,Atlas 有专门的 shell 脚本可以直接运行读取 Hive 的表结构等元数据信息同步到 Atlas 的存储库中,自动生成元数据模型,同时 Atlas 提供的 HiveHook 可以监听 Hive 的数据变化,根据 Hive 执行的 sql 推断出数据与数据之间的关系,生成血缘关系图,如果我们想要分析其他数据存储介质的元数据和血缘关系,Atlas 的支持并不是很理想。但通常情况下,我们会定时把业务库如 mysql,oracle 中的数据定时同步到数仓中整合分析,而数仓我们一般都会采用 Hadoop 的生态体系,所以这一点并不是问题。
架构图解
以下是 Atlas 的架构图解,可以看出,Atlas 所依赖的生态体系是异常庞大的,这也直接导致了它部署起来十分繁琐,本文不再讲解 Atlas 的部署,网上相关的教程有很多,感兴趣的朋友可以自己搜索尝试。
核心组件概念
Atlas 中主要有以下核心组件,这些需要我们着重了解,接下来我们通过 Rest Api 自定义建模其实就是对以下组件的增删查改操作。
1. Type
元数据类型定义,这里可以是数据库,表,列等,还可以细分 mysql 表( mysql_table ),oracle 表( oracle_table )等,atlas自带了很多类型,如 DataSet,Process 等,一般情况下,数据相关的类型在定义类型的时候都会继承 DataSet,而流程相关的类型则会继承 Process,便于生成血缘关系。我们也可以通过调用 api 自定义类型。这是一切的起点,定义完类型之后,才能生成不同类型的元数据实体,生成血缘关系,我个人更喜欢把元数据类型称之为建模。
2. Classification
分类,通俗点就是给元数据打标签,分类是可以传递的,比如 A 视图是基于 A 表生成的,那么如果 A 表打上了 a 这个标签,A 视图也会自动打上 a 标签,这样的好处就是便于数据的追踪。
3. Entity
实体,表示具体的元数据,Atlas 管理的对象就是各种 Type 的 Entity。
4. Lineage
数据血缘,表示数据之间的传递关系,通过 Lineage 我们可以清晰的知道数据的从何而来又流向何处,中间经历了哪些操作,这样一旦数据出现问题,可以迅速追溯,定位是哪个环节出现错误。
3、Altas安装
(参考链接,请结合实际情况使用)
1、https://blog.csdn.net/hshudoudou/article/details/123899947
2、https://blog.csdn.net/javaThanksgiving/article/details/130505251
4、Altas使用
Altas 成功部署之后,使用还是很简单的,这是登录界面,用户名密码默认是 admin,admin:
进入主页,点击右上角 switch to new ,使用新版界面,更直观:
页面左侧便是 Atlas 的类型树,点击树节点的某个类型,可以查看下面的实体,这里我们点击 mysql_table:
可以看到下面有很多表,这些都是我之前自己利用 Rest Api 上传定义的。
下面我们来讲解一下如何通过 Rest Api 的方式自定义类型,生成实体,创建血缘关系。
5、Atlas Rest Api 详解及示例
我们点击主页上方的 Help-》API Documentation,便可以查看 Atlas 所有的开放接口:
有一点我们需要注意,Atlas 的接口在使用的时候是需要鉴权的,所以我们构建 http 请求的时候需要带上用户名和密码认证信息,本次示例中我们使用 atlas-client-v2 开源组件来进行 Atlas 的 api 调用。
本次示例我们定义一个 my_db 类型,my_table 类型,并且让 my_db 一对多 my_table,然后创建 test_db 实体到 my_db 下,创建 test_table_source 和 test_table_target 实体到 my_table 下,并且定义 test_table_target 的数据来自 test_table_source,生成两个实体的血缘关系依赖。
自定义 my_db 和 my_table 类型
我们对 my_db 和 my_table 类型进行定义,在 Atlas 的Rest Api 中,允许一个请求定义多种类型,在这里我们先构建 json 请求体,然后再通过编码方式实现,二者对比,更容易理解,json 请求体如下(关键地方有注释):
{"enumDefs": [],"structDefs": [],"classificationDefs": [],//类型定义"entityDefs": [{"name": "my_db",//数据类型的定义,约定俗成,继承Atlas自带的DataSet"superTypes": ["DataSet"],//服务类型(便于在界面分组显示类型)"serviceType": "my_type","typeVersion": "1.1","attributeDefs": []},{"name": "my_table","superTypes": ["DataSet"],"serviceType": "my_type","typeVersion": "1.1","attributeDefs": []}],//定义类型之间的关系"relationshipDefs": [{"name": "my_table_db","serviceType": "my_type","typeVersion": "1.1",//关系类型:ASSOCIATION:关联关系,没有容器存在,1对1 //AGGREGATION:容器关系,1对多,而且彼此可以相互独立存在 //COMPOSITION:容器关系,1对多,但是容器中的实例不能脱离容器存在"relationshipCategory": "AGGREGATION",//节点一"endDef1": {"type": "my_table",//表中关联的属性名称,对应下面的 my_db"name": "db",//代表这头是不是容器"isContainer": false,//cardinality: 三种类型SINGLE, LIST, SET"cardinality": "SINGLE"},// 节点2"endDef2": {"type": "my_db","name": "tables","isContainer": true,// db 包含 table,table不能重复,所以类型设置为 SET"cardinality": "SET"},// 推导tag NONE 不推导"propagateTags": "NONE"}]
}
编码实现:
引入 pom 依赖,注意,如果要集成到自己的业务系统之中,业务系统如果使用了其他的日志框架,需要去除 slf4j-log4j12 依赖,否则日志框架会起冲突,导致启动失败,另外 atlas-client-common 中依赖了 commons-configuration 1.10,如果业务系统中有低版本依赖,记得排除,不然二者会冲突,导致 client 初始化失败。
<dependencies><!-- Apache Atlas --><dependency><groupId>org.apache.atlas</groupId><artifactId>atlas-client-common</artifactId><version>2.1.0</version><exclusions><exclusion><artifactId>slf4j-log4j12</artifactId><groupId>org.slf4j</groupId></exclusion></exclusions></dependency><!-- Apache Atlas Client Version2 --><dependency><groupId>org.apache.atlas</groupId><artifactId>atlas-client-v2</artifactId><version>2.1.0</version><exclusions><exclusion><artifactId>slf4j-log4j12</artifactId><groupId>org.slf4j</groupId></exclusion><exclusion><artifactId>log4j</artifactId><groupId>log4j</groupId></exclusion></exclusions></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency></dependencies>
引入 atlas-application.properties(必须得有,否则会初始化失败):
atlas.rest.address=http://127.0.0.1:21000
代码实现如下(对照json非常容易理解):
AtlasClientV2 atlasClientV2 = new AtlasClientV2(new String[]{"http://127.0.0.1:21000"}, new String[]{"admin", "admin"});//父类集合Set<String> superTypes = new HashSet<>();superTypes.add(AtlasBaseTypeDef.ATLAS_TYPE_DATASET);//定义myTypeAtlasTypesDef myType = new AtlasTypesDef();//定义myDbAtlasEntityDef myDb = new AtlasEntityDef();myDb.setName("my_db");myDb.setServiceType("my_type");myDb.setSuperTypes(superTypes);myDb.setTypeVersion("1.1");//定义mytableAtlasEntityDef myTable = new AtlasEntityDef();myTable.setName("my_table");myTable.setServiceType("my_type");myTable.setSuperTypes(superTypes);myTable.setTypeVersion("1.1");//定义relationshipDefAtlasRelationshipDef relationshipDef = new AtlasRelationshipDef();relationshipDef.setName("my_table_db");relationshipDef.setServiceType("my_type");relationshipDef.setTypeVersion("1.1");relationshipDef.setRelationshipCategory(AtlasRelationshipDef.RelationshipCategory.AGGREGATION);relationshipDef.setPropagateTags(AtlasRelationshipDef.PropagateTags.NONE);//定义endDef1AtlasRelationshipEndDef endDef1 = new AtlasRelationshipEndDef();endDef1.setType("my_table");endDef1.setName("db");endDef1.setIsContainer(false);endDef1.setCardinality(AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE);relationshipDef.setEndDef1(endDef1);//定义endDef2AtlasRelationshipEndDef endDef2 = new AtlasRelationshipEndDef();endDef2.setType("my_db");endDef2.setName("tables");endDef2.setIsContainer(true);endDef2.setCardinality(AtlasStructDef.AtlasAttributeDef.Cardinality.SET);relationshipDef.setEndDef2(endDef2);//entityDefsList<AtlasEntityDef> entityDefs = new ArrayList<>(2);entityDefs.add(myDb);entityDefs.add(myTable);myType.setEntityDefs(entityDefs);//relationshipDefsList<AtlasRelationshipDef> relationshipDefs = new ArrayList<>(1);relationshipDefs.add(relationshipDef);myType.setRelationshipDefs(relationshipDefs);//查询是否已有my_db类型,没有则创建SearchFilter filter = new SearchFilter();filter.setParam("name", "my_db");AtlasTypesDef allTypeDefs = atlasClientV2.getAllTypeDefs(filter);if (allTypeDefs.getEntityDefs().isEmpty()) {//请求 rest apiatlasClientV2.createAtlasTypeDefs(myType);}
执行以上代码,执行完毕后,前往 Atlas 主页查看,类型已成功创建:
查看类型模型图:
类型创建完毕,接下来我们进行实体的创建。
创建实体 test_db,test_table_source 和 test_table_target
json 如下:
//my_db 实体
{"typeName": "my_db","attributes": {"qualifiedName": "test_db","name": "test_db","description": "测试创建db"}
}
//test_table_source 实体
{"typeName": "my_table","attributes": {"qualifiedName": "test_table_source","name": "test_table_source","description": "测试创建test_table_source"},"relationshipAttributes": {"db": {"typeName": "my_db",//my_db的guid(创建完my_db后会返回)"guid": "xxxx"}}
}
//test_table_target 实体
{"typeName": "my_table","attributes": {"qualifiedName": "test_table_target","name": "test_table_target","description": "测试创建test_table_target"},"relationshipAttributes": {"db": {"typeName": "my_db","guid": "xxx"}}
}
代码实现如下:
//创建实体 test_dbAtlasEntity testDb = new AtlasEntity();testDb.setTypeName("my_db");Map<String, Object> attributes = new HashMap<>();attributes.put("qualifiedName", "test_db");attributes.put("name", "test_db");attributes.put("description", "测试创建db");testDb.setAttributes(attributes);Map<String, String> queryAttributes = new HashMap<>();queryAttributes.put("qualifiedName", "test_db");String myDbGuid = null;try {//查询不到会报错AtlasEntity.AtlasEntityWithExtInfo extInfo = atlasClientV2.getEntityByAttribute("my_db", queryAttributes);myDbGuid = extInfo.getEntity().getGuid();} catch (AtlasServiceException e) {if (ClientResponse.Status.NOT_FOUND.equals(e.getStatus())) {AtlasEntity.AtlasEntityWithExtInfo extInfo = new AtlasEntity.AtlasEntityWithExtInfo(testDb);//请求EntityMutationResponse response = atlasClientV2.createEntity(extInfo);myDbGuid = response.getGuidAssignments().values().toArray(new String[]{})[0];}}//创建与db的关系Map<String, Object> relationShipAttr = new HashMap<>();Map<String, String> dbMap = new HashMap<>();dbMap.put("guid", myDbGuid);dbMap.put("typeName", "my_db");relationShipAttr.put("db", dbMap);//创建实体 test_table_sourceAtlasEntity testTableSource = new AtlasEntity();testTableSource.setTypeName("my_table");attributes.put("qualifiedName", "test_table_source");attributes.put("name", "test_table_source");attributes.put("description", "测试创建test_table_source");testTableSource.setAttributes(attributes);testTableSource.setRelationshipAttributes(relationShipAttr);queryAttributes.put("qualifiedName", "test_table_source");try {//atlasClientV2.updateEntity(new AtlasEntity.AtlasEntityWithExtInfo(testTableSource));AtlasEntity.AtlasEntityWithExtInfo extInfo = atlasClientV2.getEntityByAttribute("my_table", queryAttributes);testTableSource = extInfo.getEntity();} catch (AtlasServiceException e) {if (ClientResponse.Status.NOT_FOUND.equals(e.getStatus())) {AtlasEntity.AtlasEntityWithExtInfo extInfo = new AtlasEntity.AtlasEntityWithExtInfo(testTableSource);//请求EntityMutationResponse response = atlasClientV2.createEntity(extInfo);testTableSource.setGuid(response.getGuidAssignments().values().toArray(new String[]{})[0]);}}//创建实体 test_table_targetAtlasEntity testTableTarget = new AtlasEntity();testTableTarget.setTypeName("my_table");attributes.put("qualifiedName", "test_table_target");attributes.put("name", "test_table_target");attributes.put("description", "测试创建test_table_target");testTableTarget.setAttributes(attributes);testTableTarget.setRelationshipAttributes(relationShipAttr);queryAttributes.put("qualifiedName", "test_table_target");try {//atlasClientV2.updateEntity(new AtlasEntity.AtlasEntityWithExtInfo(testTableTarget));AtlasEntity.AtlasEntityWithExtInfo extInfo = atlasClientV2.getEntityByAttribute("my_table", queryAttributes);testTableTarget = extInfo.getEntity();} catch (AtlasServiceException e) {if (ClientResponse.Status.NOT_FOUND.equals(e.getStatus())) {AtlasEntity.AtlasEntityWithExtInfo extInfo = new AtlasEntity.AtlasEntityWithExtInfo(testTableTarget);//请求EntityMutationResponse response = atlasClientV2.createEntity(extInfo);testTableTarget.setGuid(response.getGuidAssignments().values().toArray(new String[]{})[0]);}}
执行代码完毕后,查看类的树形图,发现已经产生了实体:
我们点击右侧的 test_db 实体,可以看到它的基本信息,也可以看到它的 relationship 信息,包含了 test_table_source 和 test_table_target 两个实体:
查看 relationship 信息,包含 test_table_source 和 test_table_target:
创建 test_table_source 和 test_table_target 的血缘关系依赖
前面我们提到,定义 test_table_target 的数据来自 test_table_source,血缘关系依赖在 Atlas 中其实也是作为实体 Entity 存在,只不过继承的父类是 Process,这样可以定义 inputs 和 outputs 属性,构建血缘关系,json 如下:
{"typeName": "Process","attributes": {"name": "test_process","qualifiedName": "test_process","description": "test_table_target 的数据来自 test_table_source","inputs": [{"typeName": "my_table",//test_table_source的guid,创建实体从返回的信息中获取"guid": "xxx"}],"outputs": [{"typeName": "my_table",test_table_target的guid,创建实体从返回的信息中获取"guid": "xxx"}]}
}
代码实现如下:
AtlasEntity lineage = new AtlasEntity();//设置为process类型构建血缘lineage.setTypeName(AtlasBaseTypeDef.ATLAS_TYPE_PROCESS);attributes.put("qualifiedName", "test_process");attributes.put("name", "test_process");attributes.put("description", "test_table_target 的数据来自 test_table_source");attributes.put("inputs", getLineAgeInfo(testTableSource));attributes.put("outputs", getLineAgeInfo(testTableTarget));lineage.setAttributes(attributes);queryAttributes.put("qualifiedName", "test_process");System.out.println(SingletonObject.OBJECT_MAPPER.writeValueAsString(lineage));try {//查询是否存在atlasClientV2.getEntityByAttribute(AtlasBaseTypeDef.ATLAS_TYPE_PROCESS, queryAttributes);} catch (AtlasServiceException e) {if (ClientResponse.Status.NOT_FOUND.equals(e.getStatus())) {//创建AtlasEntity.AtlasEntityWithExtInfo extInfo = new AtlasEntity.AtlasEntityWithExtInfo(lineage);atlasClientV2.createEntity(extInfo);}}//构建inputs和outputsprivate static List<Map<String, String>> getLineAgeInfo(AtlasEntity entity) {List<Map<String, String>> list = new ArrayList<>();Map<String, String> map = new HashMap<>();map.put("guid", entity.getGuid());map.put("typeName", entity.getTypeName());list.add(map);return list;}
执行以上代码,然后打开主页,点击 my_table 中的 test_table_source,查看 lineage 标签,血缘关系已成功构建:
至此,我们通过 Atlas Rest Api 的方式自行建模,创建实体,构建血缘关系就完成了。
元数据管理,数据治理,在当下仍然是一个热门的话题,同时,它也可以帮助我们更好的支撑企业的数据资产,更好的分析数据,为企业的发展决策提供有效的帮助。
引用链接:
1、https://blog.csdn.net/hshudoudou/article/details/123899947
2、https://blog.csdn.net/javaThanksgiving/article/details/130505251
3、原文 https://blog.csdn.net/m0_37719874/article/details/124245209
相关文章:

Apache atlas 元数据管理治理平台使用和架构
1、前言 Apache Atlas 是托管于 Apache 旗下的一款元数据管理和治理的产品,目前在大数据领域应用颇为广泛,可以很好的帮助企业管理数据资产,并对这些资产进行分类和治理,为数据分析,数据治理提供高质量的元数据信息。…...

MFF论文笔记
论文名称:Improving Pixel-based MIM by Reducing Wasted Modeling Capability_发表时间:ICCV2023 作者及组织:上海人工智能实验室,西门菲沙大学,香港中文大学 问题与贡献 MIM(Model Maksed Model)方法可以分为两部分…...

Leetcode 02.07 链表相交(链表)
Leetcode 02.07 链表相交(链表) 解法1 尾部对齐解法2:太厉害了,数学归纳推导的方法 很巧妙,这就是将链表的尾端对齐后再一起遍历,这样能满足题目的要求。因为相交之后两个链表到结束的所有节点都一样了&…...

Bootstrap的媒体对象组件(图文展示组件),挺有用的一个组件。
Bootstrap的.media类是用于创建媒体对象的,媒体对象通常用于展示图像(图片)和文本内容的组合,这种布局在展示新闻文章、博客帖子等方面非常常见。.media类使得创建这样的媒体对象非常简单,通常包含一个图像和相关的文本…...

Day2力扣打卡
打卡记录 无限数组的最短子数组(滑动窗口) 链接 思路:先求单个数组的总和,再对两个重复数组所组成的新数组上使用 不定长的滑动窗口 来求得满足目标的最小长度。 class Solution { public:int minSizeSubarray(vector<int>…...

项目经理每天,每周,每月的工作清单
很多不懂项目管理的伙伴问,项目经理每天每周每个月的工作是什么呢? 仿佛他们什么都管,但是又没有具体的产出,但是每天看他们比谁都忙,其实很简单,项目中的每个环节负责具体的事情,但是每个环节…...

Java —— 运算符
目录 1. 什么是运算符 2. 算术运算符 2.1 基本四则运算符: 加减乘除模( - * / %) 2.2 增量运算符 - * %与 自增/自减运算符 -- 3. 关系运算符 4. 逻辑运算符 4.1 逻辑与 && 4.2 逻辑或|| 4.3 逻辑非 ! 4.4 短路求值 5. 位运算符 5.1 按位与 & 5.2 按位或 5.3 按位…...
【C++ 中的友元函数:解密其神秘面纱】
友元函数,作为C中一个重要但常常被误解的概念,经常让初学者感到困惑。本文将带您逐步了解友元函数的含义、用途以及如何正确使用它们。 什么是友元函数? 在C中,友元函数是一种特殊的函数,它允许某个类或类的成员函数…...

YOLOv8涨点技巧:手把手教程,注意力机制如何在不同数据集上实现涨点的工作,内涵多种网络改进方法
💡💡💡本文独家改进:手把手教程,解决注意力机制引入到YOLOv8在自己数据集不涨点的问题点,本文提供五种改进方法来解决此问题; ContextAggregation | 亲测在血细胞检测项目中涨点,…...

牛客:FZ12 牛牛的顺时针遍历
FZ12 牛牛的顺时针遍历 文章目录 FZ12 牛牛的顺时针遍历题目描述题解思路题解代码 题目描述 题解思路 通过一个变量来记录当前方向,遍历矩阵,每次遍历一条边,将该边的信息加入到结果中 题解代码 func spiralOrder(matrix [][]int) []int {…...

函数防抖(javaScript)
防抖说明 (1)防抖的目的: 当多次执行某一个动作的时候,限制函数调用的次数,节约资源。 (2)防抖的概念: 函数防抖(debounce):就是指触发事件后&…...

日常学习记录随笔-redis实战
redis的持久化(rdb,aof,混合持久化) redis的主从架构以及redis的哨兵架构 redis的clusterredis 是要做持久化的,一般用redis会把数据放到缓存中为了提升系统的性能 如果redis没有持久化,重启的化数据就会丢失,所有的请…...

MySQL事务MVCC详解
一、概述 MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制机制。主要是通过数据多版本来实现读-写分离,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读,从而提高数据库并发性能。 MVCC只在已提交读(…...
SQL RDBMS 概念
SQL RDBMS 概念 RDBMS是关系数据库管理系统(Relational Database Management System)的缩写。 RDBMS是SQL的基础,也是所有现代数据库系统(如MS SQL Server、IBMDB2、Oracle、MySQL和MicrosoftAccess)的基础。 关系数据库管理系统(Relational Database Management Sy…...

onlyoffice的介绍搭建、集成过程。Windows、Linux
文章目录 什么是onlyoffice功能系统要求安装必备组件 windows搭建资源下载安装数据库onlyoffice安装测试 Linux搭建dockerdocker-compose 项目中用到的技术,做个笔记哈~ 什么是onlyoffice 在本地服务器上安装ONLYOFFICE Docs Community Edition Community Edition…...

37. 解数独
编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图) 数独部分空…...

git cherry-pick 合并某次提交
一、无冲突的情况 1、合并其它分支某次提交 切换到主分支,想把其他分支的某次commit修改 合并到主分支上, 可以用 git cherry-pick 命令 比如,其它分支,某次提交的commit Hash 是30e48158badc39801f1ce3cb375a07b872d6f220 &a…...
【面试HOT100】子串普通数组矩阵
系列综述: 💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:材料主要源于LeetCodeHot100进行的,每个知识点的修正和深入主要参考…...

XPSpeak软件教程-科学指南针
在做X 射线光电子能谱(XPS)测试时,科学指南针检测平台工作人员在与很多同学沟通中了解到,好多同学仅仅是通过文献或者师兄师姐的推荐对XPS测试有了解,但是对于其软件操作还属于小白阶段,针对此,科学指南针检测平台团队…...

NLP算法面经 | 腾讯 VS 美团
作者 | 曾同学 编辑 | NewBeeNLP 面试锦囊之面经分享系列,持续更新中 后台回复『面试』加入讨论组交流噢 lz从3月初脚因打球扭伤了开始,投递简历,接二连三的面试鞭尸又面试,昨天才终于上岸了,分享经验~ 腾讯PCG看点&…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...