图数据库 | 19、高可用分布式设计(下)
相信大家对分布式系统设计与实现的复杂性已经有了一定的了解,本篇文章对分布式图数据库系统中最复杂的一类系统架构设计进行探索,即水平分布式图数据库系统(这个挑战也可以泛化为水平分布式图数据仓库、图湖泊、图中台或任何其他依赖图存储、图计算及图查询组件而形成的系统)。
水平分布式系统
在开始探索之前,我们应该先明确一点,水平可扩展的图数据库系统构建的目的不是让更低配置的机器以集群的方式来承载原来单机才能完成的任务,也不是随着机器配置的降低以更大的集群规模来完成同样的任务。与此相反,在同样的机器配置下,多机构成的集群可以实现更大规模的数据吞吐,最好是实现系统吞吐率随硬件资源增长呈线性分布。
上面描述的两种路线,举例来说明。
· 路线1:原来1台机器8核CPU、128GB内存、1TB硬盘,现在要实现利用8台低配的机器,每台1核CPU、16GB内存、0.125TB硬盘来完成同样的任务,甚至效果更好。
· 路线2:原来1台机器8核CPU、128GB内存、1TB硬盘,现在以同样配置的8台实例来实现之前1台实例的数倍量级(理论上小于等于8)的挑战。
在路线1中,如果只是向客户端提供非常简单的微服务,那么1台拆分为8台是可行的,并且因为8台机器的8块硬盘提供潜在的更高的IOPS,简单数据字段的读写效率会提升,但是,1核CPU的算力可能会小于8核CPU的1/8,1核计算资源的限定会让任何操作只能以串行的方式进行,任何扩展都要与集群内其他实例进行网络通信,也会因此大幅降低任务执行效率。这意味着降配(低配)操作只适合短链条、单线程、简单类型的数据库查询操作,换言之,存储密集型或I/O优先类型的操作可以用“低配分布式”解决。这也是为什么过去在以关系型数据库为主流的数据库发展历程中,存储引擎是“一等公民”,而计算是依附存储引擎而存在的,是“二等公民”。
在对路线1的分析中,有个重要的概念:短链条任务,在互联网和金融行业中也称作短链条交易,如秒杀类操作、简单的库存查询等。它涉及的操作逻辑通常比较直白,即使在很大的数据集上,也只需要通过定位和访问极少量的数据即可返回,因此完全可以做到低延时和大规模并发。
对应于短链条任务,长链条任务则要复杂得多,它的数据访问和处理逻辑更复杂,即便在少量数据集上,也可能会牵涉相对大量的数据。如果采用传统的架构(如关系型数据库),长链条任务的操作时间会大大长于短链条,每个操作本身对于计算和存储资源的占用程度也更高,不利于形成规模化并发。图1形象地展示了这两种操作的差异性。在路线1中,短链条的任务可能被满足,但是长链条的任务则因每个实例的算力缺失而无法有效完成。典型的长链任务有在线风控、实时决策、指标计算等,对应图数据库上的操作有路径查询、模板查询、K邻查询,或者是多个子查询形成的一个完整查询任务等。

有鉴于此,在路线2中,在从1台实例扩增到8台实例时,我们不降低实例的配置,目标是让集群可以以水平分布式的方式应对如下3大挑战。
·挑战1:承载更大量的数据集。
·挑战2:提供更高的数据吞吐率(并发请求处理能力)。
·挑战3:提供兼顾长链条与短链条任务的处理能力(算力提升)。
如图2所示,在一个由多实例构成的集群内,每个实例都是典型的X86系统架构,在该架构中突出了围绕CPU的北桥(northbridge)算力部分,淡化了南桥(southbridge)相连的存储等I/O设备。事实上,每个实例都是一个可规模化并发的微系统,如CPU的多核(多线程)、CPU指令缓存、CPU数据缓存、多核间共享的多级缓存、系统总线、内存控制器、I/O控制器、外存、网卡等。以路线1的1台8核CPU与8台1核CPU为例,在充分并发的前提下,后者的计算性能低于前者,前者的存储IOPS(I/O Operations per Second)则低于后者。而路线2的1台8核到8台8核则可能实现算力与存储能力倍增。水平分布式系统的挑战1、2主要通过南桥相连的设备解决(存储、网络);挑战2、3主要通过北桥相连的设备解决(CPU、内存)。
在路线2中,算力终于成为了“一等公民”,这一点对图数据库而言至关重要。在图数据库的架构设计中,算力引擎第一次和存储引擎平起平坐,这在其他NoSQL或SQL类型数据库中是非常罕见的。只有这样,图数据库才能解决其他数据库所不能解决的复杂查询实时化、深度遍历与下钻、复杂归因分析等棘手的问题。
在我们开始设计一款水平分布式(图)数据库系统架构前,需要厘清一组重要的概念,即分区(partitioning)与分片(sharding)。一般把分片定义为一种水平分区模式,而分区则默认等同于狭义的垂直分区(或垂直分片)模式。在很多场景下,分区与分片被等同对待,但是通过水平或垂直前缀来修饰具体的切割模式。图5-20示意了一张原始数据库表如何被垂直分区及水平分区。


从图3中可以清晰地看出,在垂直分区(传统分区模式)中,不同的列被重新划分到不同的分区中;在水平分区中,不同的行则切分到不同的分片中。两者的另一个主要区别在于主键是否被重复使用,在垂直分区中主键在两个不同的分区中被100%复用,而在水平分片中则不存在复用。但是,水平分片也意味着需要一个额外的表(或其他数据结构)来对哪个分片中有哪些主键进行跟踪,否则无法高效地完成分表查询。因此,分区还是分片取决于设计者本身的喜好、具体业务查询场景中哪种方式能取得更好的效果、性价比等因素。
· 顶点数据集如何切分;
· 边数据集如何切分;
· 属性字段如何切分;
· 完成以上切分后,如何实现具体的查询及效率。
之前老夫就介绍过在图数据集中如何进行切点或切边(见下图4、图5、图6)来实现水平分布式的图计算框架。下面我们来推演一种可能的点切与边切融合的水平分布式系统的构建方式。



下图展示了一种可能的多实例分布式系统的构建方式,其中每个实例内都有各自的顶点集、边集以及其他图集相关信息,另外最重要的一个组建就是分布式ID服务(如图5-21右上箭头出处所示),任何涉及定位任意点、边在哪个(可能存在多个)实例上可以访问都需要调用这个ID服务,ID服务器只负责以下几项工作:

·插入点或边时,生成相应的ID及对应的实例ID;
·查询或更新时,提供相应的ID;
·删除时,提供相应的ID,并回收点或边的ID。
工作看似很简单,但是我们仅以插入点、边为例来分析一下可能的情况。
1)插入新的顶点。
·在唯一实例上;
·在HA主备实例对上;
·在多个实例上。
2)为顶点插入一条出边(outbound-edge)。
·在唯一实例上;
·在HA主备实例对上;·在多个实例上。
3)为顶点插入一条入边(inbound-edge)。
·在唯一实例上;
·在主备实例上;
·在多个实例上。
4)为顶点添加一个新的属性。
·在唯一实例上;
·在主备实例上;
·在多个实例上。
5)为边添加一个新的属性。
·在唯一实例上;
·在主备实例上;
·在多个实例上。
仅仅是围绕点或边的插入操作就分拆出来如上15种可能的组合情况,其他操作如更新、删除等,要考虑的情况更为复杂。在图数据库中,边是依附顶点而存在的,意味着要先有两端的顶点,才会有边,且边存在方向。关于边的方向这一点非常重要,在图论中有无向边的概念,但是在计算机代码实现中,因为涉及图遍历的问题,从某个起始顶点到终止顶点途经一条边,边是有方向的。类似地,在存储一条边的时候,需要考虑如何存储另一条反向边,否则就无法实现从起点反向遍历到终点。图5-22示意了反向边存在的必要,当我们增加一条从点B指向点C的单向边后,系统需要默认同步增加一条反向边,否则从点D无法反向触达点B或其左侧的任何相连顶点,反之亦然。

同样,删除边的时候无须删除顶点,但是删除顶点需要先从删除边开始,否则系统会立刻出现很多孤边,进而造成内存泄漏等严重问题。事实上,图数据库中批量删除顶点和边是个比较复杂的操作,特别是在分布式数据库中,操作的复杂度与点及边的数量成正比(删边还需要考虑反向边删除的问题)。删除边的一种可能步骤如下:
1)根据边的ID定位被删除边所在的实例ID(可能存在因一条边的起点、终点在不同实例上的情况,会返回两个甚至多个实例的ID);
2)(并发的)在上一步返回的每个实例上搜索定位该边ID在数据结构中的具体位置;
3)(并发的)如果采用当前边所属顶点的全部边连续存储的数据结构,把当前位置所在边与尾部边置换,并删除置换后的尾部边;
4)如果每个实例存在多个副本,同步至副本;
5)以上所有操作全部成功后,确认并提交该条边被删除成功,整个集群内的状态同步;
6)(可选的)回收该条边ID。
考虑到具体的架构设计、数据结构和算法复杂度,删除边操作的时间复杂度可能有很大的差异。一种可能的实现方式的复杂度为O(3 log N),其中N为全部点的数量,3表示类似的定位查询与实例间同步操作重复的次数。显然,如果是一个有100万条边的超级节点的删除,一整套操作非常复杂,需要先在一个实例上删除100万条边,然后再删除全部反向的100万条边,如果这些边分布在不同的实例上,会触发100万次的边对应实例查询……我们当然可以把所有边的ID整体一次性(或打包分多次查询)提交给服务器来减少网络请求次数,但是这个操作的复杂度与传统数据库中需要大批量删除某些大表中一些行的复杂程度类似。
下面举一个具体例子展示如何对图数据集进行切分,并且如何把数据存储在不同的水平分布的实例上。以图9为例,在系统设计中需要考虑如何处理以下的情形:
·支持多边图,即允许任意两个顶点间可以有多条边。
·支持自环,即可以出现从某个顶点出发回到自身的边。
·允许点、边携带有各自的属性。
·允许从任一顶点出发沿出边或入边访问相邻的顶点(换言之,支持反向边、有向图)。·允许对图数据集中的顶点进行水平切割(sharding)。
·(可选的)所有顶点的邻居在同一实例存储。
·(可选的)任一顶点关联的全部边在同一实例存储(无论该实例是否有多个备份)。
·(可选的)对图数据集中的边进行切割,被切割的边会在两个不同的实例中重复存在。

下表列出了上图中全部顶点及属性的一种可能存储结构,以及将该图一分为三后每个实例上顶点的存储情况。

表2列出了一种可能的边近邻存储数据结构,注意我们是按照顶点顺序排列的,且每个顶点的所有相邻的边按照正向与反向聚合存储。

边的切分逻辑同表1中的顶点切分逻辑,如表5-3所示。

下面验证这种简单的切图方式是否对图查询有显著的性能影响,有如下几种情况:
·查点(包括读、更新、删除,下逻辑同)。
·查边。
·查某点的全部1度邻居。
·查某点的K度邻居(K≥2)。
·查任意两点间的最短路径(假设边上权重相同、忽略方向)。
·两点在同一实例上;
·两点在不同实例上。
·其他可能的查询方式。
·图算法;
·模板查询、其他方式的路径查询等。
查点又可以细分为很多种情况:
·按照ID查。
·按照系统全局序列化唯一ID查询(又称UUID);
·按照原始ID(输入时提供)查询。
·按照某个属性查。
·按照某个属性字段中的文字的模糊匹配(全文搜索)。
·其他可能的查询方式,例如查询某个范围的全部ID等。
在最简单的情况下,客户端先向ID Server发送查询指令,通过顶点的原始ID,查询其对应的UUID以及对应的实例ID,这个查询的复杂度可以做到不大于O(log N)。
最复杂的是全文搜索,在这种情况下,客户端请求可能会被ID Server转发给全文搜索引擎,取决于引擎的具体分布式设计逻辑,该引擎可能有两种方案:
·继续向全部实例分发,并在实例上完成具体的搜索所对应的顶点ID列表;
·引擎返回含有对应顶点的ID所对应的全部实例ID以及顶点ID列表。
查边与查点类似,但是逻辑略为复杂,前面提到过由于每一条边涉及正向存储与反向存储,因此复杂度至少是顶点的2倍。另外,边隶属于顶点,可能会出现需要遍历某个顶点的部分甚至全部边才能定位某一条边的情况。当然,我们可以对所有可能出现遍历的情况进行优化,例如用空间换时间,但是依然要考虑实施的代价与性价比问题。
水平分布式系统最大的考验是如何处理关联数据查询(数据穿透),例如从某个点出发查找它的全部邻居。以图58和表5-3中的顶点1为例,要查询其全部1-Hop邻居,完整的步骤如下:
1)(可选的)根据原始ID查询其UUID;
2)根据UUID查询其所在实例的ID;
3)在该实例上定位到边数据结构中该UUID所在位置;
4)计算该阶段的全部边的数量、关联的顶点ID;
5)对关联ID进行去重运算,并返回结果集。
上操作中,最核心的逻辑是步骤4)与步骤5)。在步骤4)中,所有顶点1的出边和入边如果以连续存储的方式存在,则可以极低的复杂度O(1)计算出其出入度之和(数值为7);在步骤5)中,由于可能出现顶点1与其他顶点多次相连的情形,因此它的1-Hop的结果不是7,而是需要对与顶点1、2关联的3条边进行去重,得到的结果为4。示意如表4所示。

在上述的数据结构设计中,我们可以在任一顶点所在的实例中计算其全部的1-Hop邻居(隐含的也包括其全部的出度边、入度边),而无须任何与其他实例间的网络交互。这样相当于能把浅层(小于2层)的操作性能保持与非水平分布式架构持平,并发查询能力却倍增。
我们再来看一下如何计算顶点1的2-Hop邻居数量并返回结果集。依旧以图9为例,具体步骤如下:
1)获取并定位顶点1所在实例的ID。
2)在该实例上定位顶点1及其边数据结构,获取全部相邻顶点ID,对ID去重(获得2、3、5、6)。
3)对上一步中的顶点集合进行“分而治之”。
·对以上去重的ID查询其所在分片实例的具体服务器ID,并发送给相应的实例服务;
·顶点2、3因处于当前实例,以类似于步骤2)的方式处理;
·分片2所在实例处理顶点5、6,处理方法同上。
4)对结果集进行组装、去重。
5)向客户端返回。表5-7示意了在多个分片上计算顶点1的2-Hop邻居的流程,按照以上步骤可以分解推导如下结果:
1)顶点1处于分片1。
2)1-Hop:在分片1对顶点1操作去重后的邻居顶点为2、3、5、6。
3)2-Hop:以多线程并发的方式在各个实例上操作。
·顶点2的下一度邻居:4、1,其中1需要去重(因为已经在0度访问过);
·顶点3的下一度邻居:7、6、4、1,其中6、1需要去重(因为在1度和0度都访问过,但是此时如果不与同实例或其他实例的其他线程通信,并不知道顶点4需要去重);
·顶点5的下一度邻居:1、7、4,其中1需要去重(逻辑同上);
·顶点6的下一度邻居:1、3,其中1需要去重(逻辑同上)。
4)上一步的结果需要全部汇总,逻辑如下。
·所有分片实例向实例1汇总数据;
·顶点序列如下。
·Hop-0:1;
·Hop-1:2、3、5、6;
·Hop-2:4、1;7、6、4、1;1、7、4;1、3。
·跨步去重后2-Hop结果:4、7。
5)向客户端返回去重后的计算结果:顶点1的2-Hop邻居为2个,包含顶点4、7。

在上面的具体操作步骤中,最复杂、最核心的算法逻辑在于如何对数据进行去重。重复的数据带来了几个显著的弊端:
·非去重的数据会导致结果错误,图计算是精准计算,不是概率问题。
·非去重的数据,特别是中间结果,会导致不必要的计算量增大,耗费算力、加大网络通信压力。
但是,如何对数据去重是个非常有技巧和挑战的问题。如前面所述的推导过程,我们在步骤2)、3)及4)中对计算结果进行了去重,也就是说,在尽可能避免分片实例间通信的前提下,在每一层中都对结果集进行去重操作,并且可以在从上一层向下一层转播的过程中,把之前每一层的去重ID列表向下传播,这个操作可以以一种类似于递归的逻辑实现。
如果我们把这个K邻查询的深度扩展为3-Hop或4-Hop,或者是图的数据量级指数级增加,上面的算法是否还能够保持高效呢?
以图9为例,从顶点1出发,最大深度的Hop就是2-Hop,这时如果进行3-Hop的计算,返回的结果应当为0(空集合)。但是如果不去校验、去重每一层的数据,在不完成2-Hop之前,无法得知该图数据集并不存在相对于顶点1的3-Hop非空结果集。
以上描述的去重算法的具体实现有以下两种:
1)当前层(跳)向下传播过程中,去重数据,并向下传递自上一层传递下来的数据。
·优点:在每一层内都可以尽可能实现部分去重,降低下一层重复运算的压力。
·缺点:可能会传递大量数据,造成网络压力,且当前分片实例仅能完成局部去重。
2)当前层数据去重,但是不向下一层传播,等待到最后一层做最终的汇总、去重。
·优点:逻辑较为简单。
·缺点:可能会出现大量重复的计算(算力浪费、网络带宽浪费),且最后一层汇总的数据量大,不符合分而治之的原理。
用同样的逻辑也可以完成前面描述的其他查询及算法。笔者在这里仅仅列出了一种可能的水平分布式的实现方式,相信聪明的读者可以设计出自己的水平分布式原生图架构。
最后总结一下本章分享的分布式图系统的一些重要理念:
·分布式不是试图用多台低配的设备来取代高配的设备,并寄希望于可以获得更好的效果。毕竟(高性能的)图数据库系统不是用Hadoop的理念与框架可以实现的——如果你还停留在Hadoop时代,那么你的知识栈与认知需要一次很好的升级了。
·分布式系统设计的最重要理念就是审慎地决策哪些图计算的场景需要分片、哪些不需要分片,换而言之,分片可以解决的场景是偏浅层的查询与计算,而深度的计算与分片反向而行。
·计算机体系架构发展到今天,每一个单机、单实例的系统在底层都是一整套可以支持高并发、规模化并发的系统。这个时候,决定系统能力的是其上层的软件。高并发的底层系统并不等于软件天然地做到了高并发。
·数据结构的特征、效率决定了数据库系统的最终效率,或者说是系统的效率上限。·编程语言是有效率之分的。Python和高并发C++程序之间有成千上万倍的性能差异。
·数据库系统的开发需要对操作系统、文件系统、存储、计算、网络等诸多组件深入理解,并且需要很多工程上的调优。学术界理论结合日常工程实践是非常必要的。
·图数据库区别于传统数据库的特性有很多,最重要的是高维性,设计和使用图数据库要有图思维方式。
·图数据库的高维性意味着它的挑战不仅仅是存储,更包括计算。
相关文章:
图数据库 | 19、高可用分布式设计(下)
相信大家对分布式系统设计与实现的复杂性已经有了一定的了解,本篇文章对分布式图数据库系统中最复杂的一类系统架构设计进行探索,即水平分布式图数据库系统(这个挑战也可以泛化为水平分布式图数据仓库、图湖泊、图中台或任何其他依赖图存储、…...
【2024年华为OD机试】 (C卷,200分)- 反射计数(Java JS PythonC/C++)
一、问题描述 题目解析 题目描述 给定一个包含 0 和 1 的二维矩阵,一个物体从给定的初始位置出发,在给定的速度下进行移动。遇到矩阵的边缘时会发生镜面反射。无论物体经过 0 还是 1,都不影响其速度。请计算并给出经过 t 时间单位后&#…...
【微服务】SpringCloud 1-9章
1从Boot和Cloud版本选型开始说起 1.1Springboot版本选择 1.1.1git源码地址 https://github.com/spring-projects/spring-boot/releases/ 1.1.2官网看Boot版本 1.1.3SpringBoot3.0崛起 https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes …...
Jmeter进行http接口并发测试
目录: 1、Jmeter设置(1)设置请求并发数(2)设置请求地址以及参数(3)添加结果数 2、启动看结果 1、Jmeter设置 (1)设置请求并发数 (2)设置请求地址…...
JavaScript语言的数据结构
JavaScript中的数据结构 引言 在编程的世界里,数据结构是处理和组织数据的重要方式。数据结构的选择往往直接影响到程序的性能和可维护性。JavaScript作为一门广泛使用的编程语言,在数据结构的设计和使用上也有其独特的特点。本文将深入探讨JavaScript…...
【数据分享】1929-2024年全球站点的逐日平均气温数据(Shp\Excel\免费获取)
气象数据是在各项研究中都经常使用的数据,气象指标包括气温、风速、降水、湿度等指标,其中又以气温指标最为常用!说到气温数据,最详细的气温数据是具体到气象监测站点的气温数据!本次我们为大家带来的就是具体到气象监…...
DETRs with Collaborative Hybrid Assignments Training论文阅读与代码
关键词:协作混合分配训练 【目标检测】Co-DETR:ATSS+Faster RCNN+DETR协作的先进检测器(ICCV 2023)-CSDN博客 摘要: 在这篇论文中,作者观察到在DETR中将过少的 Query 分配为正样本,采用一对一的集合匹配,会导致对编码器输出的监督稀疏,严重损害编码器的区分特征学习…...
某国际大型超市电商销售数据分析和可视化
完整源码项目包获取→点击文章末尾名片! 本作品将从人、货、场三个维度,即客户维度、产品维度、区域维度(补充时间维度与其他维度)对某国际大型超市的销售情况进行数据分析和可视化报告展示,从而为该超市在弄清用户消费…...
码云gitee 新建仓库 添加公钥
码云gitee 新建仓库 添加公钥 文章目录 码云gitee 新建仓库 添加公钥新建仓库生成公钥管理个人公钥安全验证 码云这个网站是一个代码托管平台,在国内可以无限制的使用,在这个网站上,也可以搜索到一些github上面的内容。进入这个网站ÿ…...
SQL 基础教程 - SQL SELECT INTO 语句
通过 SQL,您可以从一个表复制信息到另一个表。 SELECT INTO 语句从一个表复制数据,然后把数据插入到另一个新表中。 SQL SELECT INTO 语句 SELECT INTO 语句从一个表复制数据,然后把数据插入到另一个新表中。 注意: MySQL 数据…...
《leetcode-runner》如何手搓一个debug调试器——指令系统
前文: 《leetcode-runner》如何手搓一个debug调试器——引言 《leetcode-runner》如何手搓一个debug调试器——架构 文章目录 什么是指令系统指令的组成部分leetcode-runner支持哪些指令如何解析用户输入的命令行指令识别流程 仓库地址:leetcode-runner …...
基于预共享密钥的IPsec实验
一、实验目的 (1)了解IPsec的原理和协议运行机制; (2)掌握IPsec身份认证的预共享密钥的配置; (3)掌握用Wireshark工具抓包分析IPsec数据包格式和协议流程。 二、实验设备与环境 &…...
Golang Gin系列-2:搭建Gin 框架环境
开始网络开发之旅通常是从选择合适的工具开始的。在这个全面的指南中,我们将引导你完成安装Go编程语言和Gin框架的过程,Gin框架是Go的轻量级和灵活的web框架。从设置Go工作空间到将Gin整合到项目中,本指南是高效而强大的web开发路线图。 安装…...
R语言绘图
多组火山图 数据准备: 将CSV文件同一在一个路径下,用代码合并 确保文件列名正确 library(fs) library(dplyr) library(tidyr) library(stringr) library(ggplot2) library(ggfun) library(ggrepel)# 获取文件列表 file_paths <- dir_ls(path &quo…...
Linux《Linux简介与环境的搭建》
在学习了C或者是C语言的基础知识之后就可以开始Linux的学习了,现在Linux无论是在服务器领域还是在桌面领域都被广泛的使用,所以Linxu也是我们学习编程的重要环节,在此接下来我们将会花大量的时间在Linxu的学习上。在学习Linux初期你可以会像初…...
.Net Core webapi 实现JWT认证
文章目录 需求准备创建JWT配置创建JWTService注册JWT创建中间件读取jwt的token在需要的接口上添加属性启动认证启动swagger的授权认证使用 需求 实现一个记录某个用户所有操作的功能 准备 创建你的webapi项目从nuget下载安装JWT资源包根据你的项目使用.net版本下载对应的jwt…...
SDL2:Android APP编译使用 -- SDL2多媒体库使用音频实例
SDL2:Android APP编译使用 3. SDL2:Android APP编译使用3.1 Android Studio环境准备:3.2 构建Android APP(1)方式一:快速构建APK工程(2)方式二:自定义APK工程(…...
gitignore忽略已经提交过的
已经在.gitignore文件中添加了过滤规则来忽略bin和obj等文件夹,但这些文件夹仍然出现在提交中,可能是因为这些文件夹在添加.gitignore规则之前已经被提交到Git仓库中了。要解决这个问题,您需要从Git的索引中移除这些文件夹,并确保…...
Visual Studio2019调试DLL
1、编写好DLL代码之后,对DLL项目的属性进行设置,选择待注入的DLL,如下图所示 2、生成DLL文件 3、将DLL设置为启动项目之后,按F5启动调试。弹出选择注入的exe的界面之后,使用代码注入器注入步骤2中生成的dllÿ…...
电力场景红外测温图像绝缘套管分割数据集labelme格式2436张1类别
数据集格式:labelme格式(不包含mask文件,仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数):2436 标注数量(json文件个数):2436 标注类别数:1 标注类别名称:["arrester"] 每个类别标注的框数&am…...
RV1126+FFMPEG推流项目(7)AI音频模块编码流程
一、AI 模块和外设麦克风的关系 AI 模块是 RV1126 芯片的一个重要组成部分。它的主要功能是将外部接入的麦克风采集到的模拟信号通过内置的驱动程序转换为数字信号。这意味着麦克风作为外设,提供音频输入信号,AI 模块通过其硬件和软件的结合,…...
从零开始启动一个Vue项目
目录 一、首先下载Node.js 二、安装vue脚手架vue-cli 三、使用vue-ui创建一个vue项目 四、vue项目目录结构 五、启动vue项目 方法一:cmd窗口启动 方法二:软件中启动 一、首先下载Node.js 可以去看我的上一篇博客: NodeJs的安装及环境…...
存储过程和触发器
目录 1、存储过程 1.1 存储过程的概述 1.2 存储过程的类型 1. 系统存储过程 2. 本地存储过程 3. 临时存储过程 4. 扩展存储过程 1.3 T-SQL创建存储过程 1.4 T-SQL执行存储过程 1.5 T-SQL查看存储过程 1.6 T-SQL修改存储过程 1.7 T-SQL删除存储过程 2、触发器 2.1 …...
改进果蝇优化算法之一:自适应缩小步长的果蝇优化算法(ASFOA)
自适应缩小步长的果蝇优化算法(ASFOA)是对传统果蝇优化算法的一种重要改进,旨在克服其后期种群多样性不足、容易过早收敛和陷入局部最优等问题。有关果蝇优化算法的详情可以看我的文章:路径规划之启发式算法之二十七:果蝇优化算法(Fruit Fly Optimization Algorithm,FOA…...
道旅科技借助云消息队列 Kafka 版加速旅游大数据创新发展
作者:寒空、横槊、娜米、公仪 道旅科技:科技驱动,引领全球旅游分销服务 道旅科技 (https://www.didatravel.com/home) 成立于 2012 年,总部位于中国深圳,是一家以科技驱动的全球酒店资源批发商…...
LLM - 大模型 ScallingLaws 的 CLM 和 MLM 中不同系数(PLM) 教程(2)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/145188660 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 Scalin…...
游戏引擎学习第80天
Blackboard:增强碰撞循环,循环遍历两种类型的 t 值 计划对现有的碰撞检测循环进行修改,以便实现一些新的功能。具体来说,是希望处理在游戏中定义可行走区域和地面的一些实体。尽管这是一个2D游戏,目标是构建一些更丰富…...
CSS布局与响应式
学习链接 Grid网格布局 前端五大主流网页布局 flex布局看这一篇就够了 grid布局看这一篇就够了 用六个案例学会响应式布局 伸缩盒响应式页面布局实战 实现响应式布局的五种方式 - csdn 如何完成响应式布局,有几种方法?看这个就够了 响应式布局总…...
PyBroker:利用 Python 和机器学习助力算法交易
PyBroker:利用 Python 和机器学习助力算法交易 你是否希望借助 Python 和机器学习的力量来优化你的交易策略?那么你需要了解一下 PyBroker!这个 Python 框架专为开发算法交易策略而设计,尤其关注使用机器学习的策略。借助 PyBrok…...
深入了解卷积神经网络(CNN):图像处理与深度学习的革命性技术
深入了解卷积神经网络(CNN):图像处理与深度学习的革命性技术 导语 卷积神经网络(CNN)是现代深度学习领域中最重要的模型之一,特别在计算机视觉(CV)领域具有革命性的影响。无论是图…...
彩色图像面积计算一般方法及MATLAB实现
一、引言 在数字图像处理中,经常需要获取感兴趣区域的面积属性,下面给出图像处理的一般步骤。 1.读入的彩色图像 2.将彩色图像转化为灰度图像 3.灰度图像转化为二值图像 4.区域标记 5.对每个区域的面积进行计算和显示 二、程序代码 %面积计算 cle…...
[Qt] Box Model | 控件样式 | 实现log_in界面
目录 1、样式属性 (1)盒模型(Box Model) 2、控件样式示例 (1)按钮 (2)复选框 (3)单选框 (4)输入框 (5)…...
内存与缓存:保姆级图文详解
文章目录 前言1、计算机存储设备1.1、硬盘、内存、缓存1.2、金字塔结构1.3、数据流通过程 2、数据结构内存效率3、数据结构缓存效率 前言 亲爱的家人们,创作很不容易,若对您有帮助的话,请点赞收藏加关注哦,您的关注是我持续创作的…...
IM聊天学习资源
文章目录 参考链接使用前端界面简单效果消息窗口平滑滚动至底部vue使用watch监听vuex中的变量变化 websocket握手认证ChatKeyCheckHandlerNettyChatServerNettyChatInitializer 参考链接 zzhua/netty-chat-web - 包括前后端 vue.js实现带表情评论功能前后端实现(仿…...
Redis 中 TTL 的基本知识与禁用缓存键的实现策略(Java)
目录 前言1. 基本知识2. Java代码 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 单纯学习Redis可以看我前言的Java基本知识路线!! 对于Java的基本知识推荐阅读: java框架…...
SpringMvc解决跨域问题的源码汇总。
看本文章前,需了解跨域的缘由。 其次,了解RequestMapping的基础原理 最后我们来解析SpringMvc是如何处理跨域问题的。 跨域信息配置 SpringMvc分为全局级别和局部级别两种,全局级别就是任何跨域请求都起作用。 全局级别 全局级别就是在配…...
25.1.17学习内容
B - 迷宫 Description 给定一个 NM 方格的迷宫,迷宫里有 T 处障碍,障碍处不可通过。 在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。 给定起点坐标和终点坐标,每个方格最多经过一次…...
【开源免费】基于SpringBoot+Vue.JS欢迪迈手机商城(JAVA毕业设计)
本文项目编号 T 141 ,文末自助获取源码 \color{red}{T141,文末自助获取源码} T141,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...
Qt之文件系统操作和读写
Qt creator 6.80 MinGw 64bit 文本文件是指以纯文本格式存储的文件,如cpp和hpp文件。XML文件和JSON文件也是文本文件,只是使用了特定的标记符号定义文本的含义,读取这种文本文件需要先对内容解析再显示。 qt提供了两种读写文本文件的方法。…...
合合信息名片全能王上架原生鸿蒙应用市场,成为首批数字名片类应用
长期以来,名片都是企业商务沟通的重要工具。随着企业数字化转型,相较于传统的纸质名片,数字名片对于企业成员拓展业务、获取商机、提升企业形象等方面发挥着重要作用。近期,合合信息旗下名片全能王正式上线原生鸿蒙应用市场&#…...
万字长文介绍ARINC 653,以及在综合模块化航空电子设备(IMA)中的作用
文章目录 一、引言二、ARINC 653背景三、整体系统架构四、应用/执行(APEX)接口五、ARINC 653 RTOS内部机制六、健康监测功能七、软件应用八、ARINC 653现状九、总结 一、引言 在现代航空领域,综合模块化航空电子设备(IMA…...
jenkins-node节点配置
一.简述: Jenkins有一个很强大的功能: 即:支持分布式构建(jenkins配置中叫节点(node),也被称为slave)。分布式构建通常是用来吸收额外的负载。通过动态添加额外的机器应对构建作业中的高峰期,或在特定操作系统或环境运行特定的构建…...
【Flink系列】5. DataStream API
5. DataStream API DataStream API是Flink的核心层API。一个Flink程序,其实就是对DataStream的各种转换。具体来说,代码基本上都由以下几部分构成: 5.1 执行环境(Execution Environment) Flink程序可以在各种上下文…...
【tailscale 和 ssh】当服务器建立好节点,但通过客户端无法通过 ssh 连接
背景 当服务器建立好节点,一切显示正常但通过客户端无法通过 vs code 中的 ssh 连接到服务器 问题解决 因为服务器是重装过的,所以忘记在服务器上下载 ssh 了。。。安装完成并启动 SSH 服务后便可正常连接! sudo apt update sudo apt in…...
TDengine 做 Apache SuperSet 数据源
Apache Superset 是一个现代的企业级商业智能(BI)Web 应用程序,主要用于数据探索和可视化。它由 Apache 软件基金会支持,是一个开源项目,它拥有活跃的社区和丰富的生态系统。Apache Superset 提供了直观的用户界面…...
PCL 新增自定义点类型【2025最新版】
目录 一、自定义点类型1、前言2、定义方法3、代码示例二、合并现有类型三、点云按时间渲染1、CloudCompare渲染2、PCL渲染博客长期更新,本文最近更新时间为:2025年1月18日。 一、自定义点类型 1、前言 PCL库自身定义了很多点云类型,但是在使用的时候时如果要使用自己定义的…...
【记录52】el-table-column 添加fixed属性 滚动条无法滑动
问题: el-table-column 添加fixed属性 滚动条无法滑动 使用element UI组件,用到el-table的el-table-column的fixed属性时,当滚动条长度小于固定列时,滚动条无法通过鼠标去点击滑动操作 原因 fixed是用来固定列的属性,其…...
华为OD机试E卷 ---最大值
一、题目描述 给定一组整数(非负),重排顺序后输出一个最大的整数。 二、示例1 用例1 输入 10 9输出 910说明:输出结果可能非常大,所以你需要返回一个 字符串只而不是整数。 三、输入描述 数字组合 四、输出描述 最大的整数 五、解题思路 字符…...
服务器迁移MySQL
由于公司原有的服务器不再使用,需要将老的服务器上的MySQL迁移到新的服务器上,因此需要对数据进行备份迁移,前提是两台服务器已安装相同版本的MySQL,这里就不再讲解MySQL的安装步骤了,可以安装包、可以在线下载、可以容…...
.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上)
系列文章目录 1、.Net Core微服务入门系列(一)——项目搭建 2、.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上) 3、.Net Core微服务入门全纪录(三)——Consul-服务注…...