Apache Doris 在奇富科技的统一 OLAP 场景探索实践

导读:随着消费信贷规模快速增长,个人信贷市场呈现场景化、体验感强的特征,精准营销、精细化风险管理以及用户使用体验的优化愈发重要。作为中国卓越的由人工智能驱动的信贷科技服务平台,奇富科技选择将 Apache Doris 作为整体 OLAP 场景统一的分析引擎,并使用 Apache Doris 替换了 ClickHouse 和 MySQL ,使得报表分析场景 SLA 达标率提升至 99% 以上,平均查询耗时降低 50%。使用 Doris 替换了 Elasticsearch,离线标签场景数据导入时效从 4 小时缩短至 1 小时,为营销活动、广告投放等提供强有力的数据支持。此外,凭借 Doris Multi-Catalog 能力,实现湖仓查询加速,彻底解决配置外表繁琐、不支持元信息自动同步等问题,极大提升了数据处理与分析的速度。

作为中国卓越的人工智能驱动的信贷科技服务平台,奇富科技(原 360 数科)致力于帮助金融机构提升智能化水平。经过多年金融领域实践,奇富科技以自身强大安全生态为依托,完成了在人工智能、大数据、云计算等技术方面的专业积累。目前,已与银行、消费金融公司、信托公司等建立广泛合作,针对不同类型金融机构的需求提供定制化解决方案,帮助客户完成数字化、智能化升级改造。

消费信贷对于促进消费起着越来越重要的作用,是助力消费恢复、激发潜在需求的重要手段之一。近年来,随着消费信贷规模快速增长,消费信贷的产品和服务也越来越丰富,个人信贷市场呈现的场景化、体验感强等特征。在此背景下,精准营销、精细化风险管理以及提升用户使用体验愈发重要。

为更贴合场景需求、提供精准运营数据支持,奇富科技自 22 年 3 月开始引入 Apache Doris,希望通过 Apache Doris 融合用户多维价值数据,基于海量数据进行实时准确的数据分析,以提供个性化的营销方案及决策支持。截止目前 Apache Doris 已在奇富科技被多个业务线应用,每日线上运行数百同步工作流,日均新增及更新的数据规模达到数十亿,承载了上百万次的有效查询。Apache Doris 的应用不仅有效提高了数据处理与分析的速度,还降低了运维成本、确保了系统的稳定性,为奇富科技实现精细化运营和营销广告精准投放提供了强有力的数据支持。

业务场景及应用现状

奇富科技大数据平台提供一站式大数据管理、开发、分析服务,覆盖大数据资产管理、数据开发及任务调度、自助分析及可视化、统一指标管理等多个数据生命周期流程。其中,最典型的数据应用服务即在线报表分析和离线标签服务,离线标签服务又包含了用户标签点查、客群画像、触发式策略生成和人群圈选四大服务。为满足不同业务数据需求,早期架构将数据分散存储在 Clickhouse、Elasticsearch、MySQL 等多个组件中,带来了数据应用和系统运维的挑战:

  • 部分 SLA 不达标:架构组件过多,原 OLAP 引擎的稳定性及可用性无法满足 SLA 要求。
  • 运维管理复杂:需同时管理多个组件,运维复杂度和难度均较高; ClickHouse 对其他组件依赖性高,扩容难度大;MySQL 单实例容量有限,需维护多个实例且不支持跨实例查询,增加了管理成本。
  • 数据治理难度高:整体数据关系复杂,数据治理难度较高,对于后续数据血缘和数据生命周期管理带来较高的成本。

除此之外,还存在一些性能及稳定性问题,具体表现为:

  • 查询耗时高:MySQL / ClickHouse 在面对复杂查询时性能较差,存在关联查询失败率高、查询响应速度慢等问题,无法满足秒级查询响应需求。
  • 导入性能差:受限于 MySQL 可承载的数据规模(千万级),无法满足大规模数据导入的要求;且 ClickHouse 导入性能较差,容易出现导入不稳定的问题。

技术选型

为解决以上问题,奇富科技计划引入一款分析型数据库以满足大部分 OLAP 场景需求,该数据库应具备以下特性:

  • 安全易治理:要求单一数据库即可满足大部分 OLAP 需求,简化数据管理流程,提高数据治理效率;要求具备完善的权限控制机制,以保证数据的安全性和隐私性。
  • 准确实时:支持数据实时导入及查询,确保数据导入不丢不重,实现 Exactly Once 语义。
  • 易用低成本:部署简单、可根据需求实现灵活扩缩容,支持 MySQL 语法、降低开发人员学习门槛,提高开发效率。

基于以上选型要求,奇富科技对 ClickHouse、Apache Doris 进行了调研。其中 Apache Doris 在导入、查询、运维等方面的性能符合选型要求,同时在社区规范性、活跃度、开放程度和可持续发展方向表现出色。因此,奇富科技选择 Apache Doris 作为整体 OLAP 场景统一的分析引擎。

奇富-选型

接下来将结合真实业务场景,介绍 Apache Doris 在奇富科技的深度应用和优化实践,更好了解 Apache Doris 如何助力奇富科技实现精准营销,提升业务收益。

Apache Doris 在报表分析场景的应用

在报表分析场景中,数据分析师通常会基于重要业务报告、图表、当前业务状况评估报告进行数据分析,旨在为业务策略决策提供重要依据。

早期架构在应对该场景时,会出现数据表同步时效 SLA 达标率(每日统计)波动较大的问题,经过深入分析是由数据同步过程所涉及组件繁多导致。不仅如此,组件繁多还增加了数据同步的复杂性,对数据源(MySQL、ClickHouse)和同步任务(如 DataX Job、Flink Job 等)的稳定性提出了挑战。

报表引擎升级

为了解决这些问题,我们使用 Apache Doris 替换了 ClickHouse 和 MySQL ,由 Doris 统一为报表提供服务,降低报表数据源的复杂度。从下图可知,Doris 架设于 Hive 数仓上层,可充分利用 Doris 强大的查询性能,为报表分析场景提供查询加速。同时 Apache Doris 支持原生 MySQL 协议,可与帆软、观远等 BI 工具无缝结合,提升了报表分析的灵活性与易用性。

奇富-引擎升级

导入任务优先级

在原先的逻辑中,Doris 对于导入任务的处理没有优先级的概念。当有大量任务同时提交时,Doris 会按照先进先出的逻辑执行任务。因此,我们主导设计并向社区贡献了导入任务优先级功能。该功能可以根据用户设定的优先级来处理导入任务,从而可以保证部分高优任务的时效性。详细流程如下图所示:

奇富-导入任务优先级

通过优先级设置,即使在任务高峰期,依然可以保证高优任务的时效性,极大提升了数据表同步时效 SLA 达标率。为数据的传输及应用提供了更灵活、高效的支持。

异地双机房高可用方案

为保障 Doris 集群的可用性及稳定性、确保在机房故障时集群仍然可读,并在故障恢复后主集群的数据能够回写,为 Doris 集群配备双机房容灾能力势在必行。经过方案调研,决定通过自行开发 Replicator 主从同步插件来实现双机房容灾建设,以下为具体的架构设计:

奇富-异地双机房

在主集群安装 Replicator 插件,该插件可以拦截并解析主集群执行的全量 SQL,经过滤操作,可筛选涉及库、表结构变更和数据增、删、改相关的 SQL,并将相关 SQL(部分 SQL 需改写)发送到从集群进行回放。

更进一步的,为了应对主集群可能遭遇意外情况,奇富科技设计了一套灵活的 DNS 解析地址切换机制。当主集群不可用时,切换 DNS 解析地址到从集群,完成主从集群的切换。

除此之外,我们还在 Doris 控制台(内部自研的 Doris 集群维护管理服务)开发了 Validator 数据校验模块,可定时对 Doris 数据表主从集群一致性情况进行校验并上报,包括元信息、行数等。

应用收益

以表同步耗时为例,利用 Doris Broker Load 方式有效降低数据导入的复杂度,提高数据导入时效性,成功将报表数据同步时效 SLA 达标率提升至 99% 以上。

奇富-应用收益

以查询时效为例,下图为引入 Apache Doris 后报表分析集群的查询时效监控,平均耗时稳定在 10s 以内、P90 查询耗时稳定在 30 秒以内 ,相比旧架构平均耗时降低了 50% 以上。随着应用程度的加深和数据规模的增长,查询性能还得以进一步提升,获得更多内部业务线的认可。

奇富-应用收益-时效
奇富-收益-时效2

Apache Doris 在离线标签服务场景的应用

在标签服务场景中,数据分析师会根据用户的多重维度信息,基于一定策略进行用户标签的打标,标签主要包括行为标签和属性标签。离线标签服务则以上述标签为基础,为下方四个场景提供服务:

  • 用户标签点查服务:在风控流程中,特征平台将查询用户的标签信息,并基于标签信息构建用户特征变量。
  • 客群画像服务:基于用户标签信息进行客户画像描绘,为电销、营销等部门制定业务策略提供数据支撑。
  • 触发式策略生成服务:电销部门基于用户标签信息,通过触发式策略生成人群包,并对筛选出的客户群进行外呼。
  • 人群圈选服务:营销部门基于用户的标签信息,对生成的人群包进行个性化广告投放。

奇富-离线标签
由于离线标签服务需同时满足四个场景的需求,因此对数据导入时效性和可用性有较高要求,以确保服务持续稳定运行。同时,需要保证用户标签查询的点查性能,支持实时查询标签信息。在人群圈选方面,还需具备精准去重和集合交并集运算能力,保证营销活动和广告投放的精准性和有效性。

奇富-离线标签-新旧架构

在原先的架构中(如上左图所示),导入的数据会逐步生成标签信息,并对标签信息进行加工、合并为 JSON 文件(合并操作是为了减少 Elasticsearch 的更新次数及负载),合并后的 JSON 文件导入到 Elasticsearch 中提供数据服务。然而,这种方式带来两个问题:

  • 旧标签服务过度依赖于合并操作,如果某个标签服务的数据出现问题,那么整个标签的合并操作就无法完成,进而影响标签服务的正常运行。
  • 数据合并操作基于 Spark 和 MapReduce 进行,处理时效可能超过四个小时甚至更长,这样长时间的处理耗时会导致场景服务错过黄金营销时间,造成业务营收的损失。

为解决上述问题,我们基于 Apache Doris 对架构进行了改造,如上图右图所示,在标签数据加工过程中,利用 Apache Doris 进行标签宽表的存储和处理,当上游标签准备就绪时,可使用 Aggregate Key + replace_if_not_null 实现标签合并和部分列更新的效果。当所有标签均更新到标签宽表后,继续将其同步到 Duplicate Key 模型的标签明细宽表中,以提升查询性能。

这样的改造使得我们能更加及时地处理标签数据,标签数据的导入时效从 4 小时缩短至 1 小时以内。此外,借助 Doris 完善的 Bitmap 索引以及高并发查询性能,实现了秒级人群圈选。在点查询方面,QPS 达到 700+,确保了查询的快速响应。

基于 Apache Doris 的湖仓查询加速实践

为缩短业务决策周期、提升数据分析师的工作效率,对于离线湖仓查询加速的重要性日益凸显。因此自 22 年 9 月起,我们开始将 Apache Doris 应用在离线查询加速场景中,彼时 Doris 仅支持以 Hive 外部表的形式进行查询,由于外部表需要配置映射关系,当 Hive 元数据发生变更时需要手动更新,人工维护成本较高,因此选择将 Hive 中数据导入进 Doris 中以实现查询加速。

奇富-湖仓查询

具体而言,会先根据查询频率对数据表优先级进行排序,通过 Doris Broker Load 将查询频率 Top 500 的数据表从 Hive 导入到 Doris。通过路由引擎定时调度收集数据表在 Doris 和 Hve 中表的元信息,包括表的字段、字类型以及数据规模。当收到查询语句时,路由器检测数据的是否在 Doris 中,如存在则会路由到 Doris 引擎,从而实现查询加速。

而该方案并不完美,依赖于对于 Hive 数据的导入。当面对大规模数据导入任务时,可能造成集群资源紧张导致查询和导入性能下降的问题,甚至可能引起集群不稳定,对业务使用产生负面影响。

为解决上述问题,我们对架构进行了进一步升级。在 Apache Doris 1.2 版本支持了 Multi-Catalog 多源数据目录,基于该能力简单配置即可将 Hive 集群的数据表完整同步到 Doris 中,解决了配置外表繁琐、元信息无法自动同步等问题。以下是数仓查询加速新方案:

奇富-湖仓-新方案

在新方案中,主要通过以下几个步骤完成数仓查询加速方案:

  • 基于 Doris Multi-Catalog 能力,将 Doris 引擎加入到查询引擎路由策略中(Internal Catalog 和 Hive Catalog);
  • 引入弹性计算节点并落地 Deploy on Yarn 方案,简化部署流程以支持灰度期间快速升级迭代、快速扩缩容支持;
  • 查询引擎实现自动路由,引擎选择对用户透明。

当用户提交查询语句后,路由引擎(即查询网关)会根据收集的数据元信息进行判断,为查询语句匹配最优查询路径。路由引擎还会分析查询涉及的分区数和表行数,来匹配最佳执行引擎( Doris 、Presto、SparkSQL ),例如当查询语句所依赖数据表都存在于 Doris 内表中且元数据一致时,将直接路由至 Doris 内表进行查询,无法命中则将查询下压,由 Doris Hive Catalog 进行查询或者通过 Presto 进行查询。

通过这种策略,用户无需关心查询由哪个引擎执行,也无需关注查询引擎间的语法差异。查询总能以最高效的方式执行,实现查询加速,并能保障结果的准确性。使用上述方案也遭遇了一些问题,接下来分享应对策略及优化方案。

Hive 元数据准实时同步

使用上述查询加速方案时,如果 Hive 元信息更新后无法准实时同步至 Doris ,用户查询时会出现结果不一致问题。为避免该问题发生,可使用 Doris 元数据自动刷新特性(基于 HMS Event Listener 实现)实现元信息准实时同步。这种方式需要在 Hive 端开启 HMS Event Listener ,并在 Doris 端开启 HMS Event 消费开关。具体实现如下图所示:
奇富-湖仓-元数据

对于 Hive 端,当开启 Listener 后,因 Hive 本身具有内置的 Listener 实现,会对 Hive 集群中 DDL 操作以及 Insert 操作进行拦截。在发起拦截操作后,生成对应的 HMS Event(事件),并写入 Hive 元信息数据库中。

对于 Doris 端,当开启消费 HMS Event 开关后,Doris 的 Master FE 节点会启动后台线程,调度式批量拉取 HMS Event,通过消费 HMS Event 获取 Hive 端的元数据变化,并将该变化同步到 Doris 内部维护的 Hive 元信息中,实现数据的准实时同步。在实施过程中也遇到了一些新的问题,在此对优化方案进行分享:

优化方案 1:Hive DDL 长时间阻塞

启动 Hive 端的 HMS Event Listener 后,Hive 处理新增表和分区时需要获取表、分区名和文件信息,生成相应的 HMS Event,而 Doris 回放 HMS Event 时并不需要文件信息。因此当 Hive 表、分区文件数过多或集群繁忙时,获取文件信息的操作会延长 HMS Event 生成时间,导致 Hive DDL 操作耗时增加。

基于此,我们重写了 Hive DbNotification Listener,屏蔽对 Hive 表、表分区文件信息收集,有效减少不必要信息的拉取与采集,缩短了 Hive 端的执行效率。

优化方案 2:消费速率与事件产生速率不匹配

Hive 集群繁忙时,DDL 或 Insert 事件频率高,且 Doris 采用单线程串行模式消费 HMS Event,可能会出现 Doris 消费速率与Hive 时间产生速率不匹配的问题。

为了提高 Doris 消费速度,我们在 Doris 端增加了预先事件合并(HMS Event Merge)步骤,过滤掉一部分 HMS Event,大幅降低了需要消费的 HMS Even 数量。预先事件合并的核心思想是判断批量 HMS Event 中是否存在可以抵消前面某个 HMS Event 产生的效果,如果是则跳过前面的 HMS Event。通过这样的方式,HMS Event 数量能够大幅度降低,进而提升了 Doris 处理 HMS Event 的消费速度

奇富-元数据-事件合并

预先事件合并原理如上图所示,第一个事件 DropPartitionEvent(db1.tbl1)和最后一个事件 DropTableEvent(db1.tbl1)针对同一张 Hive 表。DropPartitionEvent 发生在前,DropTableEvent 发生在后。在处理 DropPartitionEvent 时,Doris 会删除该 Hive 表的应分区缓存信息;在处理 DropTableEvent 时,Doris 会删除该 Hive 表的表缓存信息。由于后一个 HMS Event 产生的效果可以完全抵消前一个 HMS Event 产生的效果,因此可以跳过前面的 HMS Event。

奇富-元数据-HMS

我们对集群 4 天内所处理 HMS Event 处理情况进行抽取,从上图可知,经 HMS Event Merge 操作后,Doris 消费事件数量时显著降低,较原来减少约 2-5 倍的数量。完成优化后,再未出现消费速率低于产生速率的问题

优化方案 3:HMS Event 类型缺失,影响 FE 稳定性

针对 CDH 或者 HDP 集群 Hive 版本产生压缩格式的 Event ,新增了 GzipJSONMessageDeserializer 反序列化器进行处理。原因是 Slave FE 节点一般通过 Journal Log 方式消费 HMS Event ,如果消费失败会导致 FE 服务直接退出,通过新增 Fallback 策略可以提升消费逻辑的健壮性,尽量避免 FE 服务退出的问题

引入弹性计算节点,Deploy on Yarn 实现弹性扩缩容

当需要处理大规模数据或进行高性能计算时,需要更多计算资源提供支持。若部署的 Doris BE 集群时有上百个节点,每一个节点需要多个 CPU,那么在运行过程中需要庞大的资源支撑,从而带来较大的资源成本和部署成本。为降低资源和部署成本,我们选择引入 Doris 的弹性计算节点(Elastic Compute Node),并选择将弹性计算节点与 Hadoop 集群的其他组件(如 DataNode 节点)混合部署,能够更好地管理和优化计算资源。

在此基础上,基于 Doris 计算节点的无状态特性,可通过 Skein 进一步简化 Doris 计算节点 Deploy on Yarn 的部署流程,实现节点弹性扩缩容。在实际运行过程中,我们依据用户的查询习惯,在夜间查询较少时缩容、在白天业务高峰时扩容,最大化利用集群资源、提高资源利用率。

奇富-弹性计算

如上图,在 Yaml 文件中定义 Doris 计算节点的数量和所需资源信息,并将安装包、配置文件、启动脚本统一打包至分布式文件系统。当需进行版本升级或集群启停时,只需一行命令即可在分钟内完成整个集群上百个计算节点的启停操作。

Hive 视图查询优化

在 Hive Catalog 查询运行过程中会有偶发的查询失败问题,因此我们对数百业务用户查询失败的原因进行了深度分析,发现 28% 是由查询视图引起,24% 是由于用户使用了 Doris 无法匹配的函数导致。

奇富-视图查询失败

如下图所示,当用户发送查询请求后,在 Doris 内部将经历词法分析、语法分析、逻辑执行计划和分布式执行计划四个阶段。Hive 视图识别在第三阶段进行,即当逻辑执行计划阶段生成 Hive ScanNode 后,对其进行初始化时,Doris 会识别该表是否为 Hive 视图。如果是 Hive 视图,将直接抛出查询异常导致查询失败。

奇富-视图查询优化

因此我们对 Hive 查询执行进行了优化,将 Hive 视图的识别提前至语法分析阶段(第二阶段)进行,如果识别为 Hive 视图,则通过 HMS Client 客户端获取该视图定义的 DDL ,并将 DDL 带入 Doris 解析视图依赖的 Hive 实体表。在逻辑执行计划生成阶段(第三阶段),将生成与 Hive 实体表相对应的 HiveScanNode,查询将继续进行。通过简单改造,Doris 即可通过 Hive Catalog 实现对 Hive 视图的查询支持。

应用收益

查询加速主要得益于 Apache Doris 的 Multi-Catalog 特性,相对于外部表,Multi-Catalog 无需创建表与表之间的映射关系,可以实现元数据层的对接,如上文所述只需简单的配置,实现将整个 Hive 集群的数据表完整地同步到 Doris 中,彻底解决了以往配置外表繁琐、不支持元信息自动同步等问题

此外,借助 Doris Multi-Catalog 替代了早期架构中多个数据组件,统一了数据源入口和数据查询出口,降低架构的复杂度、缩短数据处理与查询的流程,大大提高数据查询的效率。

结束语

从 22 年引入 Doris 以来,凭借其优异的性能、较低的运维复杂度和较高稳定性,迅速在奇富科技内部多个业务场景得到大规模的应用。截止目前,生产环境共有近十套集群、上百 BE 节点、CPU Core 超过 1000+,总数据规模达到数十 TB ,每日有数百个同步工作流在运行,日新增数据或更新的规模达近百亿,每天支持业务方百万次的有效查询量。通过 Doris 的应用极大的降低了架构的复杂度,有效提高了数据处理与分析的速度,降低了运维成本,确保了系统的稳定性。

未来我们将继续深入使用 Apache Doris 、并引入 2.0 版本,为用户带来更加实时、统一的数据处理和分析体验。后续我们将重点关注存算分离架构、数据湖分析特性以及 Doris Manager 组件的应用。

奇富-结束语

  • 存算分离架构:通过存算分离架构实现集群融合,消除不同集群间 Doris 版本的差异,提供更加灵活的负载隔离策略和弹性部署支持,为用户带来更加稳定、可靠的数据处理环境,满足不同业务需求。
  • 数据湖分析特性:持续深入使用,通过统一查询引擎简化内外表数据流通过程,降低数据处理的复杂性。
  • Doris Manager 组件:为了让用户更加轻松的进行数据库的运维和管理,飞轮科技开发了一站式数据库集群管理工具 Cluster Manager for Apache Doris(简称 Doris Manager)。该工具提供轻松部署和接管 Doris 集群的功能,支持物理机和虚拟机环境。借助直观的界面,为用户提供了简单易用的可视化运维体验。同时用户还可以快捷的对节点进行扩缩容和重启,设置监控告警等操作。这将极大地提升运维效率,减少错误和中断,提高服务质量和稳定性。

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

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

相关文章

【离散数学】——期末刷题题库(树其一)

🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL&#xff1a…

城市智能图书柜需求说明书

1. 简介 1.1 项目概括 本项目主要实现智能图书柜对图书的借出、还回、续借、查询、上下架、盘点的功能,对于读者,可以进行读者证的办理,读者信息的录入和完善。 1.2 项目背景 ​ 目前大量读者距离图书馆较远,无法方便、快捷地…

IDEA运行JSP启动后页面中文乱码

源代码截图&#xff1a; 运行结果截图&#xff1a; 在<head>标签内加入代码 <% page contentType"text/html; charsetgb2312"%> 重启服务器&#xff0c;问题已改善 ————————————————— 该文仅供学习以及参考&#xff0c;可做笔记收藏…

泛型深入理解

泛型的概述 泛型&#xff1a;是JDK5中引入的特性&#xff0c;可以在编译阶段约束操作的数据类型&#xff0c;并进行检查。 泛型的格式&#xff1a;<数据类型>; 注意&#xff1a;泛型只能支持引用数据类型。 集合体系的全部接口和实现类都是支持泛型的使用的。 泛型的…

【功能更新】支持文档合并导出PDF/HTML格式;线上文章SEO设置能力优化

HelpLook功能更新速览&#x1f447; 文档管理能力&#xff1a; 1. 导出支持多篇文档合在一个HTML文件 2. 支持下载附件时保留原始文件名 3. 主页“推荐文章”支持添加外链 4. 文章URL根据标题自动生成 5. 文章支持添加“作者” 6. 博客模版支持置顶文章 1.导出支持多篇文…

通配符证书的优势有哪些?

在互联网安全的长河中&#xff0c;通配符证书以其独特的优势成为了许多网域管理员的首选。那么&#xff0c;它究竟有哪些魅力点呢&#xff1f;让我们从安全性、性价比和管理便捷性三个维度来解读一下。 安全性&#xff1a;标配的坚实防线 首先&#xff0c;从安全性角度来看&am…

邮件营销:定义、优势与策略指南

什么是邮件营销&#xff1f;跨境电商或者出海企业可能会经常使用它&#xff0c;它是传统的营销方式之一&#xff0c;在上世纪80年年代得以运用。 邮件营销&#xff0c;英文全称为Email Direct Marketing&#xff0c;缩写为EDM。它是指在收件人许可的情况下&#xff0c;通过电子…

前端开发新趋势:Web3、区块链和虚拟现实

目录 前言 Web3&#xff1a;下一代互联网 区块链技术 去中心化应用程序&#xff08;DApps&#xff09; 区块链&#xff1a;重塑数字世界 数字钱包 NFT&#xff08;非同质化代币&#xff09; 虚拟现实&#xff1a;沉浸式体验 WebVR和WebXR 三维图形 新挑战与机会 性…

final

final final关键字是最终的意思&#xff0c;可以修饰&#xff08;类、方法、变量&#xff09;修饰类&#xff1a;该类被称为最终类&#xff0c;特点是不能被继承了修饰方法&#xff1a;该方法被称为最终方法&#xff0c;特点是不能被重写了修饰变量&#xff1a;该变量只能被赋…

【SpringCloudAlibaba】Sentinel熔断限流工具的使用

一、前言 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维…

9.鸿蒙app用户界面的跳转abilityslice的跳转

9.用户界面的跳转abilityslice的跳转&#xff0c;值传递&#xff0c;数值累加 首页页面显示1&#xff0c;第2页显示2&#xff0c;再次点击返回首页3。。。 MainAbilitySlice.java 关键代码&#xff1a; 点击事件 text.setClickedListener(new Component.ClickedListener() …

vector实现循环队列

顺序队列 顺序队列是一种先进先出的线性表&#xff0c;简称FIFO。允许插入的一端称为队尾&#xff0c;允许删除的一端称为队头。因为其入队和出队操作均是&#xff08;front/rear&#xff09;指针向后移动&#xff0c;以进行结点的链接和删除&#xff0c;这就造成其使用空间不断…

Redis数据结构简介

首先对redis来说&#xff0c;所有的key&#xff08;键&#xff09;都是字符串。我们在谈基础数据结构时&#xff0c;讨论的是存储值的数据类型&#xff0c;主要包括常见的5种数据类型&#xff0c;分别是&#xff1a;String、List、Set、Zset、Hash。 1.粉丝福利 最新很多同学问…

使用SQL和Python处理Excel文件数据

目录 一、引言 二、使用SQL查询Excel文件数据 1、导入必要的库 2、创建数据库连接 3、读取Excel文件数据 4、将数据写入数据库 5、使用SQL查询数据 三、使用Python读取和处理Excel文件数据 1、导入必要的库 2、读取Excel文件数据 3、数据处理和分析 4. 将数据可视化…

ModuleNotFoundError: No module named ‘openai.error‘

ModuleNotFoundError: No module named ‘openai.error’ result self.fn(*self.args, **self.kwargs) File “H:\chatGPTWeb\chatgpt-on-wechat\channel\chat_channel.py”, line 168, in _handle reply self._generate_reply(context) File “H:\chatGPTWeb\chatgpt-on-wec…

【网络安全】—计算机网络基础

文章目录 网络必备基础物理层数据链路层与交换机网络模型OSI/TCP对等传输虚拟局域网VLAN静态路由与配置网络地址转换NAT访问控制列表ACLIP协议与IP地址分类子网掩码网关子网划分总结 计算机网络是指将地理位置不同的、功能独立的多台计算机通过通信线路连接起来&#xff0c;以功…

echarts地图map鼠标移入区域颜色(渐变)

鼠标移入透明 itemStyle下 emphasis属性 itemStyle: {// # 在未设置dataRange或 visualMap时设置有效normal: {// borderColor: rgba(12, 222, 255, 1),// borderWidth: 0.8,areaColor: {type: linear-gradient,x: 0,y: 300,x2: 0,y2: 0,colorStops: [{offset: 0,color: rg…

Unix进程间通信之简介-总体概述和引子

目录标题 0. 前言1. 概述2. 进程、线程与信息共享3. IPC对象的持续性4. 名字空间5. fork、exec和exit对IPC对象的影响6. 出错处理&#xff1a; 包裹函数7. Unix标准8. 小结 0. 前言 进程间通信这块是学习linux-c编程的关键&#xff0c; 这篇为后续进程间通信技术的引子篇&#…

jdk多版本切换环境变量管理(jdk1.8和jdk17)

jdk多版本切换环境变量管理&#xff08;jdk1.8和jdk17&#xff09; 看了很多网上的博客&#xff0c;根本都不行&#xff0c;我总结出来规律如下&#xff1a; 首先环境变量要配置成这个样子&#xff1a;这些博客都会教你们配 接着配什么classpath&#xff0c;看其他博客就行 还…

Gitee基础知识

目录 1-gitee 1.1gitee介绍 1.2git与gitee的关系 1.3在国内为什么选择Gitee 2-注册与创建远程仓库 2.1注册 2.2创建远程仓库 2.3配置ssh公钥 2.3.1公钥的生成方法&#xff1a; 2.3.2 在gitee中配置公钥 2.3.4验证公钥 3-添加与推送远程仓库master 3.1基本命令…