基于异常上线场景的实时拦截与问题分发策略
作者 | 彭阳
导读
性能中台负责MEG端研发数据的接入、传输、管理、应用等各个环节。为了应对移动应用领域中端技术的快速迭代和线上突增问题的挑战,中台提出了实时拦截与问题的分发机制,旨在在端上线的不同阶段及时发现并拦截异常上线,最大程度减少线上变更对用户体验的不良影响。本文在数据建设的时效性和准确性上进行深入的探讨,包括:变更上线的染色过程、基于染色ID的性能核心数据指标的监控、线上问题实时分发至相关模块组件和人员等。
全文7719字,预计阅读时间20分钟。
01 背景
1.1 业务背景
在快速发展的移动应用领域中,持续的技术迭代是保持APP竞争力的关键因素。然而,对于规模庞大、用户众多的APP应用,每一次的变更上线都存在引入线上问题的风险。APP的各个组件模块相互交织,一旦某处出现异常,往往会像连锁反应一样影响整个系统的稳定性,导致用户体验的下降。在以往的经验中,即便在开发和测试阶段充分验证,也难免会有一些问题在真实用户环境中暴露出来。这些问题可能表现为崩溃、卡顿、功能失效等,严重影响用户的使用体验。在过去,应对这些问题通常是事后进行问题修复,然而这种方式并不能完全避免线上问题对用户体验的不良影响。因此我们希望在业务迭代变更上线的过程中,尽可能早的发现和拦截问题,最大程度的降低问题对用户的影响。因此,性能中台引入了多级拦截和问题分发的机制,这一机制旨在在变更上线的不同灰度放量阶段,对每次上线或者放量操作进行染色形成唯一染色ID,通过对每个染色ID的核心性能数据指标进行监控,一旦发现异常,多级拦截机制将会被触发,拦截本次上线以及后续放量。同时,问题实时分发机制能够直接将问题指向导致该问题发生的模块和组件以及开发和测试人员。从而准确定位问题,并迅速修复,避免问题在更大范围内扩散。
1.2 技术背景
实时UV计算:在处理异常上线的拦截过程中,数据的实时消费以及数据的时效性的要求特别高,必须在分钟级别内完成。同时,业务方不仅需要获得异常的PV数,同时也需要获得在各个维度下异常影响的用户数(UV)。但实时UV计算不能简单地累加,这涉及到同维度间用户交集的处理。例如:A版本和B版本异常影响的用户数分别是100,但整体用户数实际上可能不足200。但是也不能直接存储用户ID,例如通过使用HashSet或者HashMap存储所有的用户ID进行去重,这面对大量用户时,会占用大量的计算节点内存资源。因此,我们采取一种计算的时效性和准确性较高的数据结构Bitmap来计算实时UV。
Bitmap 的底层数据结构用的是 String 类型的 SDS 数据结构来保存位数组,把每个字节数组的 8 个 bit 位利用起来,每个 bit 位 表示一个元素的二值状态。该数据结构能节约大量的存储,同时在用户群做交集和并集运算的时候也有极大的便利。例如,每个用户ID如果存储在HashSet或者HashMap中,需要占4个字节即32bit,而一个用户在Bitmap中只占一个bit。在做交并集运算时,例如,员工1、员工2都是程序员,员工1使用苹果手机,那么如何查找使用苹果手机的程序员用户?
直接使用位运算,使用苹果手机的程序员用户:(0000000110B & 0000000010B = 0000000010B)
异常反混淆:主要用于问题分发阶段。APP厂商在发布应用程序包时,通常会对包进行混淆操作,这是为了提高APP应用的安全性和减少反编译的风险。混淆是将源代码中的符号、名称和结构等转换为难以理解的形式,使得反编译后的代码难以还原为原始的源代码,但是APP上报的异常信息也被混淆了。反混淆操作是将混淆后的异常信息还原为可读的形式,使开发人员能够更准确地分析问题的原因,并迅速采取正确的修复措施。在APP产出应用程序包时,同时也会产生一份用于反混淆异常信息的映射文件(密码本),通过映射文件 + 解析算法对混淆的异常进行解析,即可得到已读的异常堆栈。
△异常信息反混淆过程
1.3 名词解释
性能中台:性能中台是APP性能追踪的一站式解决方案平台,为APP提供全面、实时的性能分析服务与工具链。
移动线上质量平台: 移动线上质量平台是移动端APP发包后,用来查看、分析包质量数据、进行核心指标监控/报警、变更异常拦截。
日志中台:指端日志中台,包括端日志全生命周期的能力建设。包括打点SDK / 打点server/ 日志管理平台等核心组件。
Tekes平台:App端研发平台,提供包组件管理等基础设施。
02 系统设计
2.1 整体流程
在以往的流程中,针对客户端上线变更,我们通常使用大盘性能指标来进行监控,以便进行问题定位和止损。然而,在灰度用户数量较少的情况下,线上问题往往无法在大盘性能指标中产生明显波动。当业务决定全量上线或扩大灰度用户规模时,问题就可能显现出来了。在问题定位和解决的阶段,我们过多地依赖人工干预和手动排查,这导致问题定位和解决的时间较长,并可能升级为事故。因此,在旧流程中,线上问题影响面大小主要取决于灰度用户的规模以及问题排查人员对客户端各个模块和相关人员的了解程度,这是不合理的。因此,系统设计的关键在于解决两个核心问题:首先,如何在灰度阶段拦截问题,避免其进一步扩大;其次,一旦线上问题出现,如何能够迅速进行问题召回与解决。
△线上异常实时拦截与问题分发整体流程设计图
因此,在新流程中,引入了两个关键模块:“变更拦截模块"和"问题分发模块”。对于每次平台的上线变更,必须先在变更拦截模块中进行注册,从而生成一个唯一的上线染色ID。同时,将染色ID下发至本次变更上线的用户客户端。此后,该数据集的用户日志将携带染色ID进行上报。变更拦截模块将基于染色ID的粒度进行监控和拦截,以保证在上线过程中问题的及时发现。同时,问题分发模块建立了问题自动分发机制。当一个上线变更被拦截或者在线上出现问题时,该模块将直接将问题指派给涉及问题的模块、组件,以及相关的研发和测试人员。协助业务方快速准确的定位问题,人工再介入修复。
2.2 异常上线变更拦截
异常上线变更拦截的核心思路是:为每次上线变更生成独特的染色ID,通过对每个染色ID的性能核心数据进行拦截与监控。
△异常上线变更拦截流程设计图
变更拦截流程的具体步骤如下:
① 变更上线注册: 针对厂内各个配置变更平台,需要在每次上线配置生效之前,将上线信息在染色通用服务进行注册。
② 获取染色ID: 染色通用服务通过HTTP接口为每次上线注册生成通用的染色ID,并将其返回给上线变更平台。
③ 下发染色配置: 在圈定的用户群范围内,上线变更平台将新配置和染色信息同时下发到端上的业务SDK(如AB-SDK)中。
④ 染色日志上报: 业务SDK会判定染色是否生效,如果生效,则在涉及性能核心场景的日志中附加染色ID信息,然后通过UBC-SDK上报。这些日志会通过日志中台实时转发,并写入消息队列。
⑤ 实时指标计算: 性能中台会实时订阅消息队列中的核心性能数据,例如崩溃、APP启动次数等,然后针对每个染色ID,根据多个维度(如产品线、APP版本、操作系统、地域等)形成性能聚合指标,并将其写入持久存储。
⑥ 异常拦截服务: 基于存储中的染色数据,异常拦截服务通过配置监控项来检测数据是否出现异常。一旦染色数据异常,系统会触发拦截措施并发出告警。
⑦ 异常止损: 在触发拦截和告警后,系统会通过关联染色ID和变更上线的关系,拦截继续放量以及通知业务方针对本次上线的配置回滚。
针对每次线上配置的变更,都会有一段观察期。这个观察期的长短需要适度,以确保数据的可靠性。过短的观察期会影响数据的置信度,而过长则可能降低研发效率。一般而言,每次变更后需要等待10分钟的观察期,然后再逐步增加线上流量。因此,变更拦截模块对数据时效性的要求非常高,要求数据的端到端传输时效在3分钟以内,以确保有足够的数据累积时间,从而提升监控指标的可信度。同时,染色ID的数据指标项不仅涵盖了基础的PV指标(如崩溃次数和APP启动用户数),还扩展至UV级别的指标(如受崩溃影响的用户数收敛情况和APP用户启动数)。多个指标维度下UV的计算也给数据链路的时效性和准确性带来了挑战。具体的数据流设计如下所示:
△变图更拦截数据流设计
变更拦截的数据流主要分为两个部分:
(1)实时指标计算服务;
(2) ID生成服务。
ID生成服务
ID生成服务主要用于将厂内的CUID生成INT类型的数字,从而存储到Bitmap的数据结构中。整个服务需要满足以下条件:
(1)CUID-ID的的映射全局唯一,不会出现重复的ID,且ID的整体趋势递增。
(2)高并发低延时。核心数据在计算节点内存中进行产出,减少数据库压力。
(3)高可用,服务基于云上分布式架构,即使存储mysql宕机,也能容忍一段时间数据库不可用。
在实时流中,在接收到原始数据时,先根据CUID进行keyby分发,将相同的CUID分发到同一个计算节点。对于每个计算节点:
(1)优先查询自身内存中的缓存的映射关系,若不存在,则查询redis。
(2)若redis不存在映射关系,则访问生成新ID服务。
(3)服务请求hash到号段节点上,每次去DB拿固定长度的ID List进行分发,然后把最大的ID持久化下来,也就是并非每个ID都做持久化,仅仅持久化一批ID中最大的那一个。这个方式有点像游戏里的定期存档功能,只不过存档的是未来某个时间下发给用户的ID,这样极大地减轻了DB持久化的压力。
(4)最终将映射关系写入到Redis存储中。
实时指标计算服务
在数据处理流程中,端上传的日志数据经由日志中台进行转发,进而分发到性能的各个消息队列中。实时计算服务订阅这些消息队列中的数据,以多级聚合方式进行维度指标的计算:
(1)数据分发与映射: 首先,从消息队列中获取原始数据。根据CUID进行keyby分发,将相同的CUID分发到同一个计算节点。防止相同的CUID同时访问ID-Mapping服务,导致CUID-ID的的映射全局不唯一。
(2)本地聚合: 对数据进行解析获得指标和维度,然后在每个计算节点上进行本地窗口聚合操作,将具有相同维度(版本、操作系统、染色ID等)的CUID汇总成Bitmap格式。本地聚合的目的在于减少后续的keyby shuffle阶段的数据量。
(3)全局聚合: 状态服务维护实时流的运行时状态信息和历史数据的Bitmap结果。将实时数据与历史数据进行全局聚合,从而得到最终的结果数据。同时,新的Bitmap结重新写入状态服务。其中,运行时状态信息保证了在实时流断流或重启时,能够恢复上次运行状态。加上可重入的数据源和幂等的数据输出,确保了数据流的不丢不重。
通过上述服务,当新的变更上线导致端上异常数据突增时,变更拦截服务能够在分钟级内对异常上线进行监控告警以及拦截。此外,除了向业务方披露拦截的数据指标,我们也希望中台能够直接协助业务方定位排查出问题的根因。
2.3 问题自动分发
问题自动分发的核心思路是:建立端上各个模块、组件、类方法和研发测试人员的映射关系,当发生线上问题时,通过聚类规则将经过反混淆之后问题直接指向导致问题发生的组件、模块以及负责该模块的研发测试人员。
△线上问题实时自动分发数据流
问题分发的数据流主要分为四个部分:
(1)映射文件写入存储
(2)线上异常反混淆
(3)端组件关系建立
(4)问题分发
其中(1)(2)步骤是为了将线上异常解析为可读的形式。(3)(4)步骤为将可读的堆栈进行聚类以及分发。
映射文件写入存储
在技术背景的实时反混淆介绍中,为了将经过混淆的异常信息恢复成可读的形式,关键在于使用映射文件。映射文件分为两种:一种是针对每个APP发版时生成的映射文件,用于对该版本的APP自身的异常信息进行反混淆;另一种是操作系统发版产生的映射文件,用于系统级别的异常信息的反混淆。当APP发版或操作系统升级时,通过配置流水线将相应的映射文件写入映射文件缓存中。
APP的版本又有线上和线下的区别。针对线上发版的APP版本,其版本的特点表现为每个版本的发版周期较长,线上异常数量较多,同时对数据解析的实时性要求较高。为满足这些特点,将线上发版的映射文件存储于高性能的Redis集群中。对于厂内线下测试发版的APP版本,其版本特点体现在研发测试人员都能发版,导致版本数量相对较多。然而,与线上环境不同的是,线下测试环境中构造的异常较少,而对数据解析的实时性要求较低。鉴于这些特点,更适合将线下测试发版的映射文件存储于性能稍弱但更适合存储大量数据的Hbase集群中。
线上异常反混淆
在端发生线上异常时,端会上报两条信息流。一条是崩溃的指标数据流,一条是定位堆栈的文件流。指标数据流的特点是上传信息快,包含核心信息以及简化版的异常信息,但异常信息量不全。而文件流的特点是,上传速度偏慢,但是异常信息完整(2M)。结合这两种信息流,可以获得完整的线上异常信息,供业务分析使用。但是由于两条信息流是异步上报,经常面临数据流乱序到达的问题。因此,为了解决乱序问题,我们设计了状态服务。
△状态服务数据流设计
状态服务的主要目的是处理双流乱序的数据,以确保它们能够被正确关联。其核心流程如下:
(1)同时间窗口数据关联:从消息队列中订阅数据后,首先会对处于计算节点同一个时间窗口的数据进行关联,若关联成功,则数据直接发往下游进行计算。
(2)同历史未关联的数据关联:若未成功,则查询状态服务中之前窗口中尚未被关联的数据进行关联,若关联成功,发往下游,状态存储中清除关联数据。
(3)未关联数据写入状态存储:若未成功,则将未关联的数据写入到状态存储中,等待被将来的数据进行关联。
此外,状态存储也不能无限的增长,需要有过期淘汰的策略,在该场景下,我们设置的是30min的TTL,能够关联到99.9%以上的数据。
在成功关联双流数据后,紧接着是对堆栈进行反混淆解析。反混淆的目标是将经过混淆后的异常信息还原为可读的形式。在反混淆过程中,各种类型异常的解析算法工具(如腾讯Bugly、谷歌CrashPad)通常能够在秒级别(约10秒)内完成解析操作。然而,在实时数据流处理中,仅仅满足秒级的解析时效性是不够的,需要将解析速度提升至毫秒级。因此,中台实时流中对反混淆解析进行了升级,包含算法升级适配实时流以及多级缓存在构建。
多级缓存由计算节点内存,Redis以及Hbase构成。其中,根据不同的缓存命中情况,反混淆解析的性能会有所不同。如果堆栈对应的映射文件在计算节点内存中命中,解析可以在<10ms内完成。若在Redis或Hbase中命中,则解析时间会略有延长,达到秒级别(约10秒),那么最理想的方式是将所有的映射文件都在计算节点内存中被命中。然而,由于每个版本都有对应的映射文件,且每个线上APP都有数十个版本,每个映射文件大小约为300MB,这使得无法将线上流量所需的所有映射文件都加载到算子内存中。为了解决这一问题,我们对解析算法进行了多级索引的优化。这种优化策略将整个映射文件进行了细粒度拆分,仅将异常堆栈命中的映射文件行信息加载到内存中。因此,解析算法现在不再需要将整个映射文件完全存入内存。相反,它只需存储一级索引和二级索引的关系,以及命中堆栈后获得的结果数据。这一方式在显著提高内存利用效率的同时,也解决了计算节点内存不足的问题。
△多级索引查询
但是,随着线上任务长时间运行时,我们注意到程序性能逐渐下降,导致实时流任务的数据处理经常出现延迟。我们发现问题的根本原因是计算节点缓存中的映射文件被频繁替换,导致缓存命中率低。因此,我们采用了更为适合业务场景的缓存替代算法—W-TinyLFU代替常规的LRU缓存替代策略。
△W-TinyLFU算法
相比LRU算法,W-TinyLFU:
1、热点数据适应性更强: 在高流量的场景中,一些热点数据项可能会在短时间内被多次访问。与LRU只关注最近的访问,W-TinyLFU通过维护频繁访问计数来更好地捕获这种热点数据的特征,从而更好地适应瞬时的流量变化。
2、低频数据保护:LRU在遇到新数据时,会立即淘汰最近最少使用的数据,这可能导致低频数据被频繁淘汰。W-TinyLFU通过维护一个近似的频率计数,可以更好地保护低频数据,防止它们被过早地淘汰。
3、适应性更强:W-TinyLFU在面对访问模式的变化时,能够更快地适应新的访问模式。它在长时间内持续观察访问模式,并逐渐调整数据项的权重,以更好地反映最近的访问模式。
4、写入操作考虑:LRU通常对写入操作的适应性较差,因为写入操作可能导致数据被立即淘汰。W-TinyLFU考虑了写入操作,通过维护写入时的频繁访问计数,可以更好地处理写入操作。
5、内存效率:W-TinyLFU使用了一些压缩技术来存储频繁访问计数,从而在一定程度上减少了内存占用。
经过对线上异常进行反混淆处理后,我们获得了可读的堆栈信息。接下来,我们可以对这些可读的堆栈信息进行问题聚类和分发。
端组件关系建立
组件关系变更的数据来源分为两个部分:
(1)全量数据:在APP进行发版时,通过EasyBox等工具将组件、模块等关系从包中解析出来,将该版本的组件信息上传到组件管理平台,触发组件管理平台的全量同步,将组件信息写入消息队列中。中台通过订阅组件数据,建立类方法<->组件、模块、研发人员、测试人员的关系,写入到存储中。
(2)增量数据:在组件管理平台进行人为的修改,例如修改组件类的研发、测试负责人等,触发增量同步,变更的数据写入消息队列。
通过上述数据同步,建立了类方法<->人的映射。
问题分发
通过数据流的反混淆解析,我们成功地将异常信息从二进制地址转换为可读的信息。接下来,借助聚类规则算法,我们将不同的异常堆栈逐行遍历,并优先将其聚类到厂内维护的组件和模块中所包含的类中。在此过程中,我们建立了线上问题<->类之间的关系。而在端组件关系建立的流程中,我们成功地构建了类方法<->研发测试人员之间的映射关系。将这两者的关系结合起来,我们获得了问题<->人员之间的关联。因此,当线上出现问题时,无需人工干预,系统可以直接将该问题指向负责该问题模块的负责人。负责人随后可以根据反混淆后的异常信息,进行问题的排查和修复工作。
03 总结与展望
本文主要介绍了性能中台在处理异常上线过程中,针对变更拦截和问题分发方面做的一些努力。当然,后面我们还会继续更好的服务业务,如:
1、提升影响力:对接更多的上线变更平台以及落地更多的APP。
2、提升场景覆盖度:覆盖卡顿、启动速度、网络性能、搜索性能等更多的核心业务场景。
3、提升问题聚类以及分发策略的准确度:将线上问题分发的更加合理与准确。
希望,性能中台持续不断优化,为保障APP的质量做出贡献。
——END——
推荐阅读
极致优化 SSD 并行读调度
AI文本创作在百度App发文的实践
DeeTune:基于 eBPF 的百度网络框架设计与应用
百度自研高性能ANN检索引擎,开源了
存储方案作为产品——Midgard探索
相关文章:

基于异常上线场景的实时拦截与问题分发策略
作者 | 彭阳 导读 性能中台负责MEG端研发数据的接入、传输、管理、应用等各个环节。为了应对移动应用领域中端技术的快速迭代和线上突增问题的挑战,中台提出了实时拦截与问题的分发机制,旨在在端上线的不同阶段及时发现并拦截异常上线,最大程…...

MySQL常见面试题(一)
😀前言 在数据库管理系统中,存储引擎起着核心的角色,它决定了数据管理和存储的方式。MySQL作为一个领先的开源关系型数据库管理系统,提供了多种存储引擎来满足不同的需求和优化不同的应用。除了选择合适的存储引擎,数据…...
webpack:详解entry和output一些重要API的使用
文章目录 contextentry单个入口多个入口entry相关API例一例二例三 outputoutput.assetModuleFilenameoutput.chunkFilenameoutput.clean【5.20.0版本支持】output.filename【重要】output.globalObjectoutput.library【重要】output.library.nameoutput.library.type【重要】ou…...

Spring后处理器-BeanPostProcessor
Spring后处理器-BeanPostProcessor Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过bean的初始化过程((该后处理器的执行时机)),例如:属性的填充、初始化方…...

每日一题~修剪二叉树
原题链接:669. 修剪二叉搜索树 - 力扣(LeetCode) 题目描述: 思路分析: 由题可知,我们要将原来的二叉搜索树调整为值在 low~high 之间的新二叉搜索树,接下来我们分析一下针对不同的节点的处理方…...

图像形态学操作(连通性、腐蚀、膨胀)
相关概念 形态学操作-腐蚀 参数: img: 要处理的图像kernal :核结构iteration :腐蚀的次数,默认是1 形态学操作-膨胀 参数: img : 要处理的图像kernal : 核结构iteration : 膨胀的次数,默认为1 import cv2 as cv im…...
中国这么多 Java 开发者,应该诞生出生态级应用开发框架
1、必须要有,不然就永远不会有 应用开发框架,虽然没有芯片、操作系统、数据库、编程语言这些重要。但是最终呈现在用户面前的,总是有软件部分。而软件系统开发,一般都需要应用开发框架,它是软件系统的基础性部件之一。…...

仿猫扑盒子引流神器试看神马视频-红包打卡签到领金
特点1:站内发红包,抢红包 特点2:会员可上传视频 特点3:设置每天免费试看次数…..具体看演示站点,为准 支付在后台上传收款二维码即可,支持微信和支付宝。前台提交订单后台管理员审核 环境:宝…...

WhatsApp自动营销软件是真实的吗?对做外贸有帮助吗?
出海营销少不了的就是依靠海外平台,WhatsApp作为许多海外国家和地区最受欢迎的聊天应用程序,活跃用户占到了全球人口的四分之一,有些地区比如欧洲、美洲,用户渗透率超过了80%,对海外营销的企业来说是不可缺少的销售工具…...

抖音短视频矩阵系统搭建
企业在进行短视频矩阵运营时,搭建一个矩阵号是非常必要的。矩阵号可以绑定多个不同平台的账号,批量制作和定时发布短视频,提高企业的曝光量和粉丝互动。但是,如何搭建一个有效的短视频矩阵号呢?以下是几个关键步骤。 一…...

Chinese-LLaMA-AIpaca
文章目录 关于 Chinese-LLaMA-Alpaca一、LLaMA模型 --> HF格式二、合并LoRA权重,生成全量模型权重方式1:单LoRA权重合并方式2:多LoRA权重合并(适用于Chinese-Alpaca-Plus )三、使用 Transformers 进行推理四、使用 webui 搭建界面1、克隆text-generation-webui并安装必…...

IP归属地应用的几个主要特点
作为一款优秀的IP地址定位工具,主题IP归属地的应用无疑是最好的选择之一。该应用可以将您需要查询的IP地址快速定位到所在的具体物理位置,并提供详细的地址和地图信息。接下来,让我们一起来看一看IP归属地应用的几个主要特点: 1. …...

通过解读yolov5_gpu_optimization学习如何使用onnx_surgon
onnx实战一: 解析yolov5 gpu的onnx优化案例: 这是一个英伟达的仓库, 这个仓库的做法就是通过用gs对onnx进行修改减少算子然后最后使用TensorRT插件实现算子, 左边是优化过的, 右边是原版的。 通过这个案例理解原版的onnx的导出流程然后我们看英伟达是怎么拿gs来优化…...

图像复原与重建,解决噪声的几种空间域复原方法(数字图像处理概念 P4)
文章目录 图像复原模型噪声模型只存在噪声的空间域复原 图像复原模型 噪声模型 只存在噪声的空间域复原...

Android 启动优化案例:WebView非预期初始化排查
去年年底做启动优化时,有个比较好玩的 case 给大家分享下,希望大家能从我的分享里 get 到我在做一些问题排查修复时是怎么看上去又low又土又高效的。 1. 现象 在我们使用 Perfetto 进行app 启动过程性能观测时,在 UI 线程发现了一段 几十毫…...

20230919后台面经整理
1.你认为什么是操作系统,操作系统有哪些功能 os是:管理资源、向用户提供服务、硬件机器的扩展 1.进程线程管理:状态、控制、通信等 2.存储管理:分配回收、地址转换 3.文件管理:目录、操作、磁盘、存取 4.设备管理&…...

画一个时钟(html+css+js)
这是一个很简约的时钟。。。。。。。 效果: 代码: <template><div class"demo-box"><div class"clock"><ul class"mark"><liv-for"(rotate, index) in rotatedAngles":key"i…...

红 黑 树
文章目录 一、红黑树的概念二、红黑树的实现1. 红黑树的存储结构2. 红黑树的插入 一、红黑树的概念 在 AVL 树中删除一个结点,旋转可能要持续到根结点,此时效率较低 红黑树也是一种二叉搜索树,通过在每个结点中增加一个位置来存储红色或黑色…...
掷骰子的多线程应用程序1(复现《Qt C++6.0》)
说明:复现的代码来自《Qt C6.0》P496-P500。在复现时完全按照代码,出现了两处报错: (1)ui指针(2)按钮的响应函数。下面程序对以上问题进行了修改。除了图片、清空、关闭功能外,其他…...

【vue2第十八章】VueRouter 路由嵌套 与 keep-alive缓存组件(activated,deactivated)
VueRouter 路由嵌套 在使用vue开发中,可能会碰到使用多层级别的路由。比如: 其中就包含了两个主要页面,首页,详情,但是首页的下面又包含了列表,喜欢,收藏,我的四个子路由。 此时就…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...