滴滴时空供需系统的设计和演进

news2024/11/24 5:10:36

本篇文章分为:

1.背景介绍

2.系统框架的演进

    2.1 旧系统框架的不足

    2.2 新系统框架的优势

3.系统建设思考

    3.1 存储治理

    3.2 性能优化

    3.3 研发提效:配置化能力升级

3.总结

1. 背景介绍

时空供需系统(SDS, supply and demand system)是为了满足滴滴网约车业务中供需特征需求而设计和研发的系统。可以在空间(地图网格、区县、城市)和时间(瞬时、分钟、小时)粒度上计算和存储海量供需特征,供算法模型实时查询和读取。随着业务的发展,算法模型也在不断演进迭代,从简单的模型到现在复杂的深度学习模型,在预估效果变得愈发精准的同时,对时空供需系统的性能和迭代效率等方面也提出了更多的挑战。本文将重点阐述时空供需系统在建设过程中遇到的挑战以及优化思路。

2. 系统框架的演进

2.1 旧系统框架的不足

在供需调节业务发展的初期,工程同学为了提升支撑策略迭代的效率,抽象出了一套通用的配置化供需特征生产框架,取得了巨大的业务收益。该框架由四部分组成:特征计算、特征配置中心、在线特征获取和离线特征落表,如下图所示:

7b1236f26a8d9c2ab4dad46f85b094f8.png

  • 特征计算:从MQ消费各类业务事件,流式计算产出实时供需特征

  • 特征配置中心:对于计算逻辑相对简单的特征,在配置中心中维护MQ topic和特征的映射关系,以及特征的计算逻辑,实现配置化。对于复杂特征,则在特征计算模块中开发定制化代码来实现

  • 在线特征获取:支持以特征语义、时间、空间等多个维度对供需特征数据进行查询

  • 离线特征落表:定时拉取KV存储中的增量数据,由大数据组件采集到HIVE表中

随着业务的发展,业务逻辑的精细化,以及数据体量的增大,该框架逐渐暴露以下不足:

  • 存储层水平扩展方面:系统架构只支持单redis存储集群,随着redis集群规模的增大,扩容带来的收益呈现边际递减

  • 可用性方面:使用单一redis存储集群,如果存储层出现集群级别的故障,系统缺乏故障转移的能力,且服务恢复时间可能较长

  • 性能方面:特征查询qps 50W+,由于特征加载逻辑比较复杂,扇出到存储层的qps高达800W+。耗时敏感业务对特征查询耗时的SLA非常严格(15ms内)。旧框架在高峰期存在性能瓶颈,p99耗时超出SLA,影响算法模型的预估效果。

  • 研发效率方面:随着业务的精细化和智能化,特征语义和口径预发复杂,需要定制化开发代码的场景增多,研发周期较长。

本文也将从存储治理、性能优化和配置化能力升级三个方面重点阐述系统建设中技术思考和优化思路。

2.2 新系统框架优势

efb7ed62c222f2a60f6df331d1031cbd.png

  • 存储架构方面:引入路由层支持多存储集群,提升存储资源水平扩展能力;数据读写路由支持热更新,避免单点故障升级为整体故障

  • 性能方面:通过多级缓存、特征与计算、延迟队列替换定时任务等组合优化,有效缓解度放大、耗时毛刺等问题,服务体验显著提升

  • 研发效率方面:对特征生产流程进行组件化改造,实现组件编排能力,实现特征生产全流程配置化

3. 系统建设思考

3.1 存储治理

在新系统框架中,存储架构治理需要达成的目标是:

  • 提升系统存储层的水平扩展能力

  • 提升系统可用性,降低存储单点故障的影响面和恢复时间

在业界主流的redis集群实现中,集群中redis实例的数量均不能无限制的扩展:

  • codis:随着redis实例数量的增多,zk会出现性能瓶颈

  • redis cluster:redis实例数量越多,gossip协议广播风暴对于网络以及服务器压力也就越大

为了提升系统存储层水平扩展的能力,我们决定将现有redis存储集群拆分成若干个规模较小的集群,同时为系统引入数据路由层负责管理多存储集群的路由策略。当某个redis集群无法继续扩容时,能够接入新的redis集群来水平扩展系统的容量。同时也便于把每个集群的规模控制合理的范围内,提升资源的投入产出比。从可用性的角度看,鸡蛋也不能都放在同一个篮子里。

3.1.1 存储集群拆分

2df7b501403a8d61282f43846a549ba4.png

  • 特征读写路由配置:维护不同特征读写的目标集群。支持热更新,支持一键式的数据迁移均衡和故障转移操作

  • 存储集群路由路由层:解析读写请求中的特征,匹配路由配置中的目标集群,把请求转发到相应的存储集群

3.1.2 数据拆分的原则

通过某个唯一标识把数据均匀散列到多个存储集群,或者按照时间分段存储保证范围查询的效率,是几种常见的分表方式。然儿基于时空供需特征自身的读写特点,以上方式并不能很好解决扩展性的问题,具体的分析和方案如下:

一是根据特征key的hash值进行拆分

  • 优势:拆分后各redis集群的数据量均衡

  • 劣势:供需特征的key是由"特征语义"、"空间标识"、"时间片"几部分组成的,按照这种方式进行拆分,如果业务方批量查询某个语义的特征在多个空间和时间片上的值,请求可能会扇出到多个redis集群,最悲观的情况是拆分后每个新redis集群的qps都与老集群相同。同时在增加或者减少redis集群数量时,所有集群都需要进行数据迁移,扩缩容的复杂度和成本会更高

二是按照特征语义进行拆分

  • 优势:相对第一种方式,特征批量查询的流量扇出较小。同时不同语义的特征读写的复杂度不同,体现在使用的redis命令的数量和时间复杂度有比较大的差异,因此这种方式也在资源层面起到了"快慢隔离"的效果,偶发慢查询对整体服务质量的影响更小。

  • 劣势:需要为每个语义的特征独立维护读写集群的路由配置,相比hash这种无业务属性的拆分方式,维护成本略高

可以发现第二种数据拆分方式更加契合时空供需系统的业务和数据特点。关于要为不同语义特征单独维护读写路由配置的痛点,在实际落地的过程中进行了一些优化:

  • 初期通过开发自动化脚本,批量、自动为特征配置增加读写路由配置,降低人力投入成本

  • 同时配套建设集群管理平台,中长期可以通过页面化的方式来管理每个特征的读写路由配置,以更灵活的根据业务需要热更新特征的路由配置,高效完成存储层的扩缩容和故障转移等操作

3.1.3 平滑升级

由于系统在线上提供的是短时供需特征,redis数据的ttl较短,可以采用”双写“+”切流“的方式把老集群的数据迁移到新的redis集群,在这个过程中,更重要是保障系统的稳定性以及数据的一致性,同时升级过程需要做到上游业务无感知。以下介绍保证服务质量的核心方案:

d1e4da8eb06c91fd7825121db973036e.png

  • 测试阶段:依托QA团队为供需系统打造的自动化测试平台,研发同学可以快速搭建两套分别模拟线上稳定版本和升级后版本的特征读写流量的测试环境。基于平台的引流功能,两套测试环境可以实时消费线上mq事件流量的拷贝,并通过自动化程序对两套环境产出的数据进行diff校验

  • 双写阶段:对新旧redis集群中,相同的特征key进行diff率校验,确保在双写时间大于数据ttl后,新旧集群中的数据完全一致

  • 读切流阶段:为特征查询接口建设空值率和同环比环化率监控和告警。如果出现数据掉底和数值异常波动,研发人员可以第一时间感知并进行止损

  • 止损预案:整个升级过程中涉及的线上操作,均可以通过配置中心一键回滚,保证出现异常时有手段可以快速止损

3.2 性能优化

由于线上有大量算法模型使用实时供需特征,redis存储层的流量压力巨大(在redis实例层统计的请求qps为千万级别)。在系统升级的过程中,团队在性能优化上进行了以下的探索:

  • 本地缓存:每次查询redis之后,把特征值缓存在本地内存中,降低对redis的请求压力

  • 预计算:对于高qps大模型需要的特征数据进行预计算聚合,降低对redis实例层的流量扇出

  • 引入延迟队列优化定时任务毛刺

3.2.1 本地缓存

前文提到,供需特征数据是按照“特征语义”、“空间标识”、“时间片”三个维度进行分组存储的,从时间维度上,分钟和小时粒度的特征,在时间片切换之后(例如,时间从M自然分钟流逝到M+1自然分钟),之前时间窗口的特征数据就不会再发生变化了。对于这类”静态特征“,进行本地缓存的收益会比较大,同时由于系统在业务上是提供的是短时供需特征,绝大部分算法模型读取的都是最近半个小时之内的数据,数据存在热点可以进一步提升本地缓存的收益。

提升缓存命中率

由于在线特征查询api的qps在百万级别,查询服务的节点数量较多(200+台docker)。前后查询相同特征数据的业务请求有比较大的概率被均衡到不同的查询服务节点上,因此早期特征本地缓存的命中率并不理想。

实际上,系统的特征存在两种时间属性:静态类和实时类。其中实时特征,在每次读取时需要基于存储中的数据计算其瞬时值,无法进行本地缓存操作。因此这里的优化思路是把查询服务独立为两个集群,分别提供这两类不同时间属性特征的查询服务。在api服务对请求的特征按照时间属性进行分组,依托服务发现组件,分别路由到不同的查询服务集群。

755bc2cf0e4303c863e4185e25e5fc0e.png

在方案评估阶段,经测算系统静态特征的查询流量占比在60%以上,不过在最终落地之后提供静态特征查询服务的集群只使用了相当于原集群40%的docker数,这是因为独立集群之后,由于节点数的减少,本地缓存的命中率有大幅度的提升,由于与redis之间的网络IO减少,可以使用更少的资源抗住相同的查询流量。

在经过一段时间的调试之后,目前的优化收益是:特征查询服务节点数减少20%,静态特征本地缓存命中率提升20%,高峰期redis集群响应时间下降30%。

3.2.2 特征预计算聚合

上游部分"大模型"请求qps高并且每次拉取的特征数量多,在按照特征语义进行redis存储集群拆分之后,这类模型的流量会打到多个redis集群,有必要针对这类场景进行特征的预计算处理以降低集群维度的流量扇出。

特征查询流量高、拉取特征数量多的大模型,是供需系统负载的主要来源。无论从业务还是技术视角上看,优先投入资源优化这类场景的收益都是更大的。对于大批量的特征查询,mget请求会被redis集群路由到多个redis实例之上,对于redis实例的负载压力更大。其中任意redis实例出现耗时抖动,都会拖慢整个请求的响应,体现在特征查询服务上就是高峰期的耗时毛刺较多。

这些大模型的预估在同一个时空下,可以有同一个用户或者多个不同的用户多次触发,前文提到系统中的静态特征在相同时空下是固定的,因此在时空维度下这是一个典型的读多写少的业务场景,可以采用复杂写简单读的思路进行优化。

7502e574fb1063b4566771f6b9e9d16d.png

如上图所示:

  • 在特征产的过程中,记录在哪些时空下大模型关联的特征发生了变化

  • 在时间片切换之后,触发预计算任务,对上一个时间片的的增量数据按照时间和空间两个维度进行聚合,聚合数据包含一个时空下所有不同语义特征的数值

  • 进行特征查询时,需要读取key的数量有时间、空间、语义的笛卡尔积,缩减为时间和空间两个维度

实际上预计算任务本身也会增加存储层的压力,但对于这个读多写少的业务场景,并不是主要的矛盾。在实际上线之后redis实例层的访问流量降低了35%,大模型特征查询的p99耗时下降了15%。

3.2.3 引入延迟队列优化定时任务

供需特征除了支持线上算法模型的实时预估之外,也需要把特征数据落到hive表中,以支撑离线的模型训练和数据分析。过去采用的是分钟增量的采集的方式,系统需要标记新增的数据,通过分钟级的定时任务,从redis读取增量的特征数据打印日志,并由大数据组件采集日志同步到离线的hive表。

其中的痛点是,定时任务从redis读取增量数据时,请求脉冲比较严重,导致在定时任务执行过程中,由于存储复杂比较大,其他业务流量的耗时上涨比较明显。以下是考虑过的优化思路:

  • 打印特征生产的明细日志,每分钟把明细日志聚合为大数据采集需要的格式

    • 优势:不需要额外访问redis

    • 劣势:明细数据日志量过大,本地磁盘存储成本高。日志聚合任务需要考虑系统崩溃等异常场景下的数据完整性,实现难度比较大

  • 控制从redis读取增量数据的并发度和请求间隔

    • 优势:可以在不需要大的架构层面的改造的前提下,打平请求脉冲

    • 劣势:不同时段增量特征的数据量差异较大,并发度和请求间隔很难评估和控制。尝试类似TCP拥塞控制等自适应算法的实现复杂度较高,增加系统的维护成本

  • 引入延迟队列,每次特征数据发生变化,向延迟队列写入一个标记,下一分钟消费该标记进行特征读取和落日志的操作

    • 优势:架构清晰简单清晰、可随机打散延迟时间实现流量的平滑

    • 劣势:需要对架构进行一定的改造

综合评估实现复杂度和平滑效果,我们最终采用了第三种方案,如下图所示:

a80da9adf7e98ec03bb0ed3416dfbbe8.png

对于每条特征数据只有在每分钟第一次变化时需要把数据的标识写入延迟队列,通过把延迟时间均匀打散到下一分钟的0-59秒,从而保证下游的落表服务可以平滑的从redis拉取增量数据,相比之前的落表定时任务,对存储几乎没有脉冲式请求流量。

3.2.4 其他优化项

在性能优化的过程中主要采用的是自顶向下的思路,上述提到的系统架构和业务模型的升级,收益和人力投入相对更加明确和容易评估。以下简要阐述一些我们采用过的其他通用的性能永华手段,同样也取得了不错的收益:

通过golang pprof、监控打点等手段发现低效的bad code

  • 对频繁创建释放的小对象进行池化处理

  • 对线程安全的对象进行单例模式改造

  • 对并发访问的map,进行分桶,降低锁的粒度

使用GC trace优化服务的GC

  • 通过耗时监控发现服务每分钟前10秒的p99耗时是其他时间的5-6倍。在进行gc trace分析时,可以看到存在gc pause时间高达50ms的情况(与前10秒的耗时毛刺比较接近),绝大多数goroutine在gc时进行了长时间的辅助标记,初步怀疑耗时毛刺是由于程序gc引起的。基于以上我们想到,供需特征带有时间属性,每分钟前10秒会有大量新的数据写入本地缓存,此时缓存组件会创建大量新对象。通过调研,把缓存组件替换为"0 gc"的bigcache库之后,耗时毛刺基本消除(绿色为优化后的耗时曲线)       

    b6803a393c2d907c2e83a4209a05d08f.png

3.3 研发提效:配置化能力升级

在旧的系统框架中,研发效率存在两个主要的痛点:

  • 由于配置化能力较弱,需要大量的代码开发来实现口径比较复杂的特征,迭代周期较长

  • 特征生产逻辑缺乏模块划分和功能抽象,导致在相似的特征之间,已有的代码和能力无法复用。

b1d16f5a21a133b6c15fef6338b59655.png

优化思路:

  • 梳理过往所有特征的语义和计算逻辑,对特征生产流程进行抽象和拆分,进行组件化设计。

  • 如上图所示,特征生产流程被解耦为多个职责单一的组件,彼此只依赖数据交互的协议,因此每个组件都可以横向扩展,灵活组合以适应不同的业务场景。组件化的设计在提升灵活性和复用性的同时,进而可以通过配置化的方式对特征生产流程进行编排

  • 将特征配置抽象为两部分:组件编排配置和组件本身的配置。

例如,某个特征的生产需要消费上游mq中发单事件,以下是消息解析组件的配置示意

{
  --- 忽略其他配置项 ---
  "data_parser": "json", // 指定使用json解析器作为数据解析组件
  "parser_conf": [
    {
      "field": "order_id",
      "jpath": "info.order_id",
      "type": "int"
    }, // order_id在json数据中的路径和类型
    {
      "field": "city_id",
      "jpath": "info.city.city_name",
      "type": "string"
    } // 城市名在json数据中的路径和类型
  ]
  --- 忽略其他配置项 ---
}

如果该特征的生产逻辑中需要对订单的字段进行一些业务校验,以下是相应的规则校验组件配置

{
  --- 忽略其他配置项 ---
  "rule_engine": "default", // 指定规则引擎组件的实现
  "rule_engine_conf": "city_id == 'abc'" // 业务规则表达式
  --- 忽略其他配置项 ---
}

4. 总结  

架构的设计与优化需要立足于业务的发展情况。当业务处于探索期时,流量负载较低且上游业务不强依赖供需系统,单存储集群的架构在实现成本和复杂度上都是最优的选择。配置化能力的升级,也是在业务模式成熟和稳定之后才进行的,此时我们可以合理的对业务模型进行抽象。在维护大规模服务时,团队保持良好的编码风格和规范同样非常重要,数组的扩容、对象的频繁创建在高并发系统中都可能引发服务性能的急剧恶化。

时空功能系统发展到今天,离不开各团队的支持。非常感谢QA团队在自动化测试和数据质量监控的建设方面给予的支持和上游各业务团队从业务视角给出的大量有建设性、可落地的建议。感谢大家!

延展阅读

065efb5b77339bc52e3d9dc8f41865f9.png

8d9af8c0a2901fed24fbfd49d0042aaf.png

a1588abd8bb5c28edbcc85f16ed9486d.jpeg

a1c93e4d77d4f9889c3dec9b44ea6aeb.png

END

作者及部门介绍 

本篇文章作者李心宇,来自滴滴网约车MPT团队(Marketplace Technology)。团队致力于打造世界顶尖的智能交易平台,包括订单分配、司机调度、拼车、定价、补贴等方向,通过不断探索机器学习、强化学习等前沿技术,完善交易市场设计,实现资源最优化分配,力求解决正在发生的以及潜在供需失衡的状况,最大程度满足平台多样化的出行需求,持续优化乘客体验和保障司机收入,提升业务经营效率,引领出行行业变革与发展。

招聘信息

团队后端、算法需求招聘中,欢迎有兴趣的小伙伴加入,可以简历投递至pennyqinpei@didiglobal.com,或扫描下方二维码简历直投,期待你的加入!

高级研发工程师

岗位职责:

1. 负责核心的派单引擎架构的设计与开发,分布式匹配计算系统等;

2. 负责分单,导流、供需预测等复杂策略的架构设计和开发;

3. 负责新业务模式的探索。

13f4c9ab8cda11c6c26e21f30a94e667.png

高级算法工程师

岗位职责: 

1.研究包括独乘、拼乘模式下的各种交易匹配、分单调度、乘客预期等算法,持续提升核心交易效率;

2.利用因果推断、运筹规划、机器学习等技术,提升供需预测、补贴定价等运营核心算法效果;

3.利用算法技术实现集团各业务线用户的高效增长,优化流量运营效率;

4.通过机器学习技术解决司乘纠纷和体验问题,打造良好司乘体验和平台秩序,构建司乘公平的判责能力,守护司乘的安全。

d9b30b40ed0ecba449cf55560b25062b.png

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开箱即用的工具函数库xijs更新指南(v1.2.6)

xijs 是一款开箱即用的 js 业务工具库, 聚集于解决业务中遇到的常用函数逻辑问题, 帮助开发者更高效的开展业务开发. 接下来就和大家一起分享一下 v1.2.6 版本的更新内容以及后续的更新方向. 贡献者列表: 1. 计算变量内存calculateMemory 该模块主要由 zhengsixsix 贡献, 我们可…

leetcode练习(汇总插入区间)

文章目录 题目一:汇总区间题目二:插入区间 语言:python 工具:jupyuter 题目一:汇总区间 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说&#xff0c…

“程序员,致敬!”

手机震动,提醒着我3年前参加研发的应用迎来了一次重大升级。我按下开源社区提供的合并请求按钮,与开源社区的朋友分享我对这个项目的改进。不久,一条消息提醒我合并请求已被其它社区成员审核通过。 这种远程协作、开源分享的方式是如今广泛存…

chatgpt赋能python:Python数值计算指南:为什么它是一种强大的工具

Python数值计算指南:为什么它是一种强大的工具 当谈到数值计算时,许多人所想到的编程语言都是MATLAB和R。然而,Python也在数值计算领域有着强大的地位。Python是一种令人难以置信的通用编程语言,它不仅为数据科学和机器学习提供了…

行人检测重识别yolov5+reid(跑通+界面设计)

行人检测重识别yolov5reid(跑通界面设计) 参考源代码: github 权重文件: 根据github上面的网盘进行权重下载: 检测:将 ReID_resnet50_ibn_a.pth放在person_search/weights文件下,yolov5s.pt放person_sear…

如何用海外代理辅助对接 ChatGPT

许多朋友问我有没有好用的海外代理。说实话,真的好用的并不多。 最近我了解到了一家还不错的海外代理,叫做 IPIDEA,我已经使用了一段时间了,觉得质量挺不错。 你可能知道,我最近在进行一些 ChatGPT 相关的研究&#xf…

DTW 2023:戴尔发力多云战略与边缘运营

近日,2023戴尔科技全球科技大会(Dell Technologies World,简称DTW)在美国拉斯维加斯如期而至。 作为戴尔科技集团一年一度的科技盛宴,本届DTW吸引了众多业界人士的关注。而作为本届大会的重头戏,戴尔科技集…

Spark学习笔记

1 spark简介 (1) spark是基于内存计算的分布式并行计算框架,如今已成为apache软件基金会最重要的三大分布式计算系统开源项目之一(Hadoop、Spark、Storm)。 (2) spark组件 (3) spark组件应用场景 Spark Streaming:提供流计算功能 Sparl SQL&#xff1…

Python实现循环的最快方式(for、while等速度对比)

众所周知,Python 不是一种执行效率较高的语言。此外在任何语言中,循环都是一种非常消耗时间的操作。假如任意一种简单的单步操作耗费的时间为 1 个单位,将此操作重复执行上万次,最终耗费的时间也将增长上万倍。 while 和 for 是 …

JavaCV - 图像暗通道去雾

一、效果图 二、实现原理 暗通道先验:首先说在绝大多数非天空的局部区域里,某一些像素总会有至少一个颜色通道具有很低的值,也就是说该区域光强是一个很小的值。所以给暗通道下了个数学定义,对于任何输入的图像J,其暗通道可以用下面的公式来表示:其中JC表示彩色图像每个…

SOFA Weekly|SOFAChannel#33 直播预告、Layotto 社区会议回顾与预告、社区本周贡献

SOFA WEEKLY | 每周精选 筛选每周精华问答,同步开源进展 欢迎留言互动~ SOFAStack(Scalable Open Financial Architecture Stack)是蚂蚁集团自主研发的金融级云原生架构,包含了构建金融级云原生架构所需的各个组件&am…

阿里、腾讯、京东齐降价:云计算迎来新拐点

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 618源于京东创办日(创办于2004年6月18日),发展至今,618已然成为中国两大最火爆的消费节点之一。每年618,京东都会推出覆盖全品类的优惠政策,并以严格的…

chatgpt赋能python:Python捕获所有异常

Python 捕获所有异常 Python是一种易用、高效的编程语言,广泛应用于Web开发、数据科学、人工智能等领域。在Python编程中,异常处理是一项重要的技能,因为程序总会出现各种异常情况,如输入错误、网络错误、程序崩溃等等。Python提…

矿井水除氟——高矿化度矿井水氟化物深度降解的技术方案

高矿化度矿井水是指含有高浓度溶解性矿物质的废水,通常指的是含有高浓度钠、钙、镁、铁、铝、钾等离子的废水。这些离子通常来自于废水所处的环境、工业或生产过程中使用的原材料和化学品。高矿化度的废水通常具有高盐度、高电导率、高硬度等特征,对环境…

(十七)ArcGIS 属性表生成GUID字段

ArcGIS 属性表生成GUID字段 目录 ArcGIS 属性表生成GUID字段 1.GUID概念2.GUID格式3. ArcGIS 属性表生成GUID字段3.1新建GUID字段3.2生成GUID字段 1.GUID概念 全局唯一标识符(GUID,Globally Unique Identifier)是一种由算法生成的二进制长度…

堆的实现+堆的应用(堆排序和Topk)

珍惜当下的一切,相信未来的一切都是美好的。 -- 丹尼尔迪凯托目录 一.堆的概念及结构 二.堆的各种函数的实现 1.结构体的内容 2.堆的初始化 3.堆的插入 4.堆的向上调整法 5.验证堆的向上调整法 6.堆顶的删除 7.堆的向下调整法 8.返回堆…

【Python】使用百度AI能力

知识目录 一、写在前面✨二、百度AI能力介绍三、植物识别四、总结撒花😊 一、写在前面✨ 大家好!我是初心,希望我们一路走来能坚守初心! 今天跟大家分享的文章是 Python调用百度AI能力进行植物识别。 ,希望能帮助到大…

欧盟加密监管法案通过,美国急了?

万众期待的欧盟《加密资产市场监管法案》(Markets in Crypto-Assets Regulation,简称MiCA)终于在5月16日尘埃落定。 尽管在4月20日,该方案已在欧洲议会全体会议上投票通过,但直到5月16日,包括27个国家的欧盟…

STP生成树协议(超详细小白也能看懂)

一、为什么要用STP 为了提高网络可靠性,交换网络中通常会使用冗余链路。然而,冗余链路会给交换网络带来环路风险,并导致广播风暴以及MAC地址表不稳定等问题,进而会影响到用户的通信质量。生成树协议STP(Spanning Tree …

计算机毕业论文选题推荐|软件工程|系列十

文章目录 导文题目导文 计算机毕业论文选题推荐|软件工程 (***语言)==使用其他任何编程语言 例如:基于(***语言)门窗账务管理系统的设计与实现 得到:基于JAVA门窗账务管理系统的设计与实现 基于vue门窗账务管理系统的设计与实现 等等 题目 基于(***语言)多媒体教室管理…