小米基于 Flink 的实时数仓建设实践

news2024/12/24 21:32:46

摘要:本文整理自小米软件开发工程师周超,在 Flink Forward Asia 2022 平台建设专场的分享。本篇内容主要分为四个部分:

    1. 小米数仓架构演变

    2. Flink+Iceberg 架构升级实践

    3. 流批一体实时数仓探索

    4. 未来展望

Tips:点击「阅读原文」查看原文视频&演讲 ppt

小米数仓架构演变

1.1 数仓架构现状

4a52953b8f02eb169516fcb4803ba59e.jpeg

在介绍演变前,我们先来了解下小米当前的技术现状。

上图展示的是小米目前的技术架构,在存储侧我们主要应用数据湖 Iceberg 和自研消息队列 Talos,计算层主要应用 Flink 和 Spark,他们统一运行在 Yarn 上,统一通过 Metacat 获取元数据信息,并通过 Ranger 来进行统一的鉴权服务。我们内部使用 Spark 和 Presto 来支撑 OLAP 查询场景,并通过 Kyuubi 来实现路由。

在实时数仓场景中,我们选择 Flink 作为计算底座,Hive、Talos、Iceberg 作为存储底座,其中,消息队列 Talos 作为传统 Lambda 架构的通用选择,在我们内部占比较大且很稳定,Iceberg 作为一款优秀的湖存储,兼具时效性和低成本,其使用占比也在逐步提升,使用到 Iceberg 的 Flink 作业在总占比中已经达到近 50%。

6412b74382c8f41cf06906d5854635ce.jpeg

我们对内部实时链路进行了统计,Iceberg 在大多数场景下已经对 Hive 进行了替换,对分钟级的实时链路进行了较好的支撑;因为使用 Iceberg 搭建的实时链路目前仅能达到分钟级的时效,消息队列仍有着较高占比。

1.2 数仓架构演变

92f6300ab85406515de3bd9d4c12e932.jpeg

接下来看下小米内部数仓架构的演变历程。

在引入数据湖前,针对日志埋点这样的聚合计算场景,业务会使用离线计算来搭建链路,采集模块会将日志或埋点数据统一收集到消息队列中,Flink 消费消息队列中的数据实时写入 ODS 层 Hive 表,下游的计算则采用 Spark 或者 Hive 按小时或天进行清洗、聚合。显然,这样的链路处理延迟和成本都较高,这些离线作业往往都在凌晨进行调度,给整个集群带来较大压力。

8bf2f71084b7ba1c3b2d4ca2ee6e6d6a.jpeg

针对 CDC 数据源,实时数据通常会通过消息队列进行流转,保证处理的实时性,数据在消息队列中以 Changelog-Json 的格式进行存储。但为了保证计算的准确性,业务链路通常会使用 Lambda 架构来搭建,会额外引入一条离线链路。离线链路基于 Hive 或 Kudu 构建,ODS 层使用 Spark Streaming 近实时导入,部分场景也会定期全量导入,下游计算依赖 Spark 做定时调度。显然,这样的架构开发和维护的成本都会很高。

6ab3286883bdea53b0d4ffed2d05945d.jpeg

带着上面的问题,我们想要对批和流链路进行统一,并能够满足低成本和低延迟,为此我们引入了 Iceberg,在引入 Iceberg 初期,小米内部的使用以 v1 表为主(v1 表是数据分析表,支持 Append 类型数据的增量读写)。因为 Flink 旧架构(1.12 版本)读取 Iceberg 的数据时效性不高,所以在日志埋点场景的应用主要是替换了 Hive,使用 Iceberg 来存储 ODS、DWD 层数据,可以降低存储成本,同时配合 Spark、Presto 可以获得更快的查询速度。

99a8ca1c031b02ced32a6d82fc278efd.jpeg

针对 CDC 数据源的场景,在初期也同样以替换 Hive 为主以获取更低的成本。

4ffb2a09db5584e928cd6fe394579017.jpeg

在中期,我们开始大规模使用 Iceberg V2 表,并对 Iceberg V2 表的生态不断进行完善,v2 表在 v1 表的基础上支持了行级别的更新和删除,同时也支持了 Merge on read 模式,并且有着不错的性能。业务的实时链路也可以完全依赖 Flink 和 Iceberg 来进行搭建。之前的日志埋点链路通过 Iceberg v2 表的升级后,使用 Flink+Iceberg v2 替换了原先的 Spark + Iceberg v1,将链路时效性由小时级提升至分钟级。

113178043076ab660315b09f6c09e219.jpeg

由于 v2 表能够支持行级别的更新,而且数据实时可查,原本针对 CDC 数据源的 Lambda 架构链路可以升级到 Kappa 架构,由 Flink 和 Iceberg v2 表来构建,兼顾时效性和成本,依赖 Parquet+ZSTD 压缩,存储成本相比于原先 Parquet+snappy 能够节省 30%。

1.3 当前架构遇到的问题

efaa437a67b4643666b002a84b04a6e9.jpeg

经过我们一段时间的使用,我们发现目前 Iceberg 能够很好地兼顾成本、查询效率,社区的很多优化也以离线为主,但在实时场景中存在着时效性和稳定性方面的不足,距离消息队列仍有差距,同时,Iceberg 作为统一的存储 Format,在实际消费时需要读取底层文件,而 v2 表有着多种文件类型,读取时需要组织 DataFile 和两类 DleteFile(Equlity delete 和 Position delete)的关系,逻辑较为复杂。

我们在基于 Flink+Iceberg 的实时链路构建中,经常会遇到以下两类问题:

  • 链路实时性略差,相比于消息队列仍有差距,目前仅能够稳定在 15 分钟左右。

  • 链路稳定性略差,经常因为链路中一张表的消费积压导致作业失败,从而使得整体链路不可用,严重依赖人工干预。

Flink+Iceberg 架构升级实践

2.1 基于 Flink1.12 的旧架构实现

22001102f16285831f3ac35a954924fe.jpeg

针对上述的两个问题,我们对 Flink+Iceberg 的架构进行了升级。

上图中的实时数仓链路由多张 Iceberg 表和多个 Flink 作业组成,其中 Iceberg 负责数据的存储,Flink 负责数据的清洗、流转,显然对一条链路的实时性和稳定性支撑,Flink 起了关键作用。在一个 Flink 流式作业中,数据会经过读取、计算、写入,在实际场景中,我们发现数据的读取效率低,严重影响了作业吞吐,后续的相关优化也主要围绕读取部分展开。

122029ee16a28620148de2579d57089c.jpeg

在优化前,我们的 Flink+Iceberg 实时链路主要依托于 Flink 1.12 版本构建,在 1.12 版本中,读取逻辑被拆分为 Monitor 和 Reader 两个算子,在进行增量消费时,Monitor 算子扫描 Snapshot 中的文件,并组织成 Split 发往下游给 Reader 算子消费。这样的架构做到了很好的扫描和读取逻辑分离,但是仍有几点重要缺陷,例如:

  • 由待消费文件组织成的 Split 在 Monitor 和 Reader 算子之间是单向传递的,下游 Reader 算子只能够通过反压来告诉 Monitor 当前消费存在积压。

  • Monitor 目前的文件扫描操作是完全由时间来驱动的,单一的时间驱动显然不能够完美兼容生产场景的波动。

  • Iceberg V2 支持行级别更新和删除,存在着主键的概念,为了保证全局消费的顺序性,我们手动限制了 Reader 算子的并发为 1。

2.2 旧架构遇到的主要问题

6a4fcfa5ac0f0362c0023e1703151785.jpeg

这样的缺陷在实际作业中会有实时性和稳定性两大问题表现。在实时性方面,存在着消费速度慢、消费存在波动;在稳定性方面,存在着 Task OOM,Checkpoint 容易超时。

376cda78d3f7c73133ce30cc533f50d0.jpeg

在时效性方面,目前主要有三个主要问题,分别是消费波动、消费延迟以及消费瓶颈。Split 的单向传输和扫描操作时间触发使得消费存在波动和延迟,考虑 Monitor 算子在一个时间周期内仅能够发送固定数量的 Split 给下游进行消费,如果 Split 数量少,那么 Reader 算子会有部分时间处于空闲状态,导致消费存在波动,存在资源浪费;而如果一个周期内下发的 Split 超过了 Reader 的消费能力,那么 Split 就会在 Reader 侧堆积,占用额外的堆内存。同时固定的扫描间隔也会导致消费的延迟,新数据需要等待一定扫描间隔后才可能被消费到,如果用户配置了一个较大的扫描间隔,那么数据的时效性会继续降低。

7eb766a395535fe89a858c2f28345aa7.jpeg

这样的机制不仅影响着实时性,对稳定性也有不小的影响。Monitor 和 Reader 的单向同步机制,使得消费需要指定间隔和间隔内下发的 Split 数,未消费完的 Split 会存储在堆内存中,积压较多会导致 OOM、Full gc 频繁,Task 吞吐降低。

同时,旧架构的 SourceFunction 在实现数据下发时需要持有 Checkpoint 锁从而保证数据下发和状态更新的一致,而 Reader 算子 Checkpoint 粒度仅细化到 Split 级别,所以 Reader 算子需要长时间去持有 Checkpoint 锁,只有消费完一个 Split 后才会释放,这在下游处理慢,反压情况下是致命的缺陷,很容易导致 Checkpoint 超时。这些点一同促使着作业稳定性的降低。

2.3 基于 Flink1.14 的新架构实现

d285f16aac0b151c4cde33197ea8ea5f.jpeg

为了解决上述实时性和稳定性问题,我们在社区基于 FLIP-27 的改动上改进了读取逻辑,主要涵盖了上图右侧的七点,其中双向通信,Monitor 逻辑移至 JobManager 是 FLIP-27 的关键优化点。我们内部主要对后面的五点进行了优化,分别是 Snapshot 的依次扫描、自适应的扫描模式、分区多并发消费等。

9416f7cc5c2dbe46826502225a2f737a.jpeg

增量消费 Iceberg 存在着两种方式,分别为依次扫描 Snapshot 和合并多个 Snapshot 扫描。在合并多个 Snapshot 的扫描模式中,需要依赖 Merge on read 模式,用后续 Snapshot 中的 Delete 文件对当前 Snapshot 中的 Data 文件数据进行过滤。如果合并多个 Snapshot 进行消费,那么一个 DataFile 可能会关联到很多后续 Snapshot 的 DeleteFile,使得 Split 的组织变得复杂,同时 Reader 算子在使用 DeleteFile 过滤 DataFile 时,需要将 Equlity delete file 全部读取到内存中,这也很容易导致 Task 产生内存问题。

考虑到上面的文件组织复杂度和内存文件,我们默认选择将扫描模式设置为了依次扫描,该模式可以更好地追踪数据变化,并且降低文件组织复杂度,避免了在合并多个 Snapshot 模式中因为 Delete 文件较大而产生的内存问题,对稳定性更加友好。

49e830644fed033717ddc9ffe0587c47.jpeg

旧架构中,扫描逻辑主要由时间驱动,定时触发,在新架构中,我们引入了自适应的扫描模式,增加了事件驱动,解决了消费波动和 Task 潜在的内存问题。在实际扫描过程中,动态 Enumerator 会根据内存中 Buffer 的反馈进行决策,小于阈值就立刻执行扫描操作,保证 Reader 能够连续消费,大于阈值就阻塞扫描,避免将更多的 Split 缓存在内存中。

63846a796097f0a2b3ff5b89bb47f964.jpeg

在新架构中,我们针对 v2 表实现了并发消费,将原本的单一队列 Buffer 按照下游 Task 拆分成多个队列 Buffer,Iceberg 表中不同分区的数据文件会按照写入排序,并被 Hash 到不同的队列,实现消费的分区有序。

同时为了保证各个 Task 消费数据的对齐,我们使用 Snapshot 的提交时间来生成 Watermark,引入 AlignedAssigner 来实现统一的 Split 分配,在分配端实现对齐,保证下游各个 Task 消费数据的对齐。

52788ad9a8ae1bbfc7c8502fe20bd389.jpeg

上面我们讲到的自适应扫描只能解决单个 Source 实例的问题,在实际应用中,部分场景仍有潜在稳定性问题存在,例如集成场景中的指标拆分,将一张表的数据拆分至多张表;数仓场景中,对同一张表进行多次引用,筛选不同部分的数据进行 Join。在这两个使用场景中,因为不满足 Source 复用规则,会有多个读取同一张 Source 表的实例存在。

在 Flink 中,Source 的复用受 Partition、Limit、Project、Filter 影响,以 Project 和 Filter 为例。上图左边的 SQL 描述了 Project 下推导致的复用失效,因一个字段的区别,同一份数据就会被读取三次;上图右边的 SQL 描述了 Filter 下推导致复用失效的场景,即使选取的范围有很大重复,但 Source 仍不会得到复用。由于复用的失效,同一个表的相同 Split 会在内存中存在多份,依然有出现内存问题的可能。

8541b23468c3cbd65f3c550a82cbfdb5.jpeg

为了优化这种情况,我们引入了两种方式。

  • 通过规则来自动对当前不符合复用的 Source 算子执行复用。

  • 支持在 SQL 中手动指定表实行强制复用。这样的优化在减少内存占用、减少数据重复读取方面有着不错的效果,节省作业资源的同时也增加了稳定性。

323f1dd4fef9381203c59884f811290e.jpeg

通过切换至新架构,消费 Iceberg 表的平均扫描间隔降至小于 1 秒,单个 Task 吞吐提升至 70 万条每秒,实时数仓链路新鲜度提升至 5 分钟内。

流批一体实时数仓探索

上一章介绍了 Flink 读取 Iceberg 架构的优化,这一章将主要介绍小米在 Flink 流批一体实时数仓上遇到的问题以及相关探索。

b3fd5a89dfbbb885de54aba17d20f84b.jpeg

遇到的问题可以归结为三类。

第一类是数据波动,实时数仓中数据是不断变化的,由于 Flink 回撤机制的存在,-U 和+U 会拆分为两条数据写入,在-U 写入,+U 未写入时执行查询,会查询到异常数据,而在+U 写入后又能查询到正常结果。

第二类是计算不确定性,Flink 中算子的状态过期会导致计算结果的不确定。同时针对这部分异常数据,往往没有简单的对比、修复手段,这也会导致实时链路产生的数据修复起来比较麻烦。

221250a5b074ce224e1cb9a3a3f6b221.jpeg

针对数据波动问题,考虑到下游绝大多数系统都能够支持 Upsert 写入,我们引入了写入前数据丢弃能力,用于丢弃无关紧要的数据,将其称为 Drop Operator。该算子作用在 Sink 节点前,能够根据配置丢弃指定类型的数据。

针对 Flink 聚合增量数据写入 ADS 层 MySQL 的场景,可以配置丢弃-U,避免 ADS 层查询波动。同样,该配置可以很方便的将 Changelog 流丢弃-U 和-D 转为 Append 流,满足一些特殊的业务场景。

a7a034b3773c8525de63fdbce1a61e75.jpeg

在解决计算的不确定性前,我们需要先了解其产生的原因。在 Flink SQL 中,状态起着重要作用,正确的中间状态是计算结果正确的必要条件。但显然,目前状态的保持是昂贵的,我们需要一个状态过期策略来进行平衡。

在 Flink 内部,有着 Watermark 清理和 TTL 清理两类算子。Watermark 可以根据业务的需要去生成,清理的策略根据实际使用场景制定,所以对计算结果影响可控。而依赖 TTL 清理的这类算子,在 Flink SQL 中状态过期的策略无法得到准确控制,只能设置一个统一的状态过期时间,往往因为过期时间设置不合理或者满足不了业务需求,从而产生预料之外的计算结果。

7c46949dbf4ee3be657607dcff48ba1a.jpeg

例如物流、服务单场景,订单从创建到关闭的时间跨度往往很长,很容易出现在订单还没有结束前,状态就过期了。为了解决订单跨度时间长导致状态丢失的问题,业务会设置一个离线的 Topic,通过离线链路定期往离线 Topic 里补数据,补充的数据重新流入实时链路中,将过期状态重新补回。

3430e1f04c1e5c5e4e8c1caca555c3b8.jpeg

针对由状态过期而导致的计算不确定问题,我们有两种解决思路。

  • 针对定时批量补状态,我们尝试从源头解决问题,让状态按需过期,减少额外链路维护。

  • 针对定时批量修复异常数据,我们想要提供更加简单方便的修复途径。

a9196a577177794ccf84cb165095b0dc.jpeg

为了能够让状态按需过期,我们引入了算子级的状态清理功能,将清理规则应用范围从作业细化到各个算子,将清理规则从时间规则拓展到业务规则,并通过 Query Hint 对算子提供灵活、方便的定义。

f72283d0ce13c583f780c9bab19eafb8.jpeg

目前该功能支持两类算子,分别是 Group 聚合算子和 Regular Join 算子,上图表格为支持的参数,通过 TTL 的参数可以设置该算子状态的过期时间,condition 参数可以填写清理规则,为了方便判断,清理规则需要是布尔表达式。

fe2542951e038371da53edf018c22a02.jpeg

上图的 SQL 展示了求某类商品总销量的聚合计算逻辑,该聚合算子状态保存时间为 30 天,覆盖了作业级的 1 天保存时间,且当商品状态为售罄或下架,那么就清除该商品的状态,这意味着有关该商品的销售记录后续不会再出现。

在聚合算子里,我们加入了一个状态清理的检查器,将用户设置的清理规则经过 codegen 转换为 Java 代码,在聚合计算后进行规则检查,匹配成功后执行清理。

ab1462667761e65dde3b67fd333122b1.jpeg

同样针对 Join 算子,状态清理检查器的实现类似,只是在 Join 算子会对左右表的状态分别进行清理,清理完后会去对方状态中将引用计数-1。

上图的 SQL 示例描述了一个物流表的 Join 场景,左表为物流订单表,保存着订单状态以及更新时间,右表为维度表,保存着该订单的一些基础信息,包括创建时间。在图中的例子中,Join 算子的状态清理不再依赖 Proctime,只依赖于运单状态和运单的持续时间。

98599c4692ab405314a2e2d488838ae3.jpeg

虽然算子级状态清理能够解决一部分需求,但它的使用门槛较高,且并非所有业务都有明确的清理规则,一个简单方便的修复手段才适用于所有场景。如果想要用 Flink Batch 对数据进行修复,目前有 INSERT 和 OVERWRITE 两种方式。使用 INSERT 实现 SQL 逻辑较为复杂,且只能对数据进行覆盖,不能删除;OVERWRITE 的修复方式粒度较粗,而且会使下游实时作业产生较大波动。

在这样的场景下,我们使用 Flink 实现了 Merge 语法。Merge 语法会对两个数据源做 Join,并可以针对不同的 Join 情况执行增、删、改操作,对下游影响小。

f600768224925cbb460b2edfd428ddd9.jpeg

在具体的实现上,我们在原本的 Calcite 语法上完善了 Merge 语法的解析逻辑,支持为每个 Action 设置独立的判断条件,在 Schema 匹配情况下支持 Insert * 和 Update * 语句,简化逻辑。

在 SQL 校验阶段,Merge 逻辑会被转为 Outer Join 和多个 Merge Action 的结合。在优化阶段,目前我们会根据实际的 Merge Action 情况来优化 Join 方式,将默认的 Outer Join 改写为 Anti Join 或者 Inner Join,减少处理的数据量。

最终,Merge 逻辑会生成 Join 和 MergeAction 两个算子,Merge Action 算子根据上游 Join 情况来生成增、删、改数据并发往下游。由于 Flink SQL 目前提供了优秀的流批一体架构,可以复用当前的逻辑,将增删改数据写入下游数据系统。

72e6fe90fde7f52693d6f43549d0cd44.jpeg

在我们内部,Spark 和 Flink 目前都支持 Merge 语法,但 Spark 在框架层只提供了语法侧的支持,Runtime 层的支持在 Iceberg 侧由插件实现。Flink 则在框架中实现了语法和 Runtime 层的支持,使得 Merge 的功能更加通用,也能够支持更多存储系统。目前,在我们内部,Flink merge into 入湖和入库场景使用较多。

05543e4228943afc67a96b13a445267d.jpeg

因为实现原因,Spark 在我们内部目前仅能支持 Merge into 入湖,所以我们在 Merge into 入湖场景下对 Spark 和 Flink 的处理速度做了测试,目前中小批量数据的 Merge 操作 Flink 执行速度会略快,大数据场景下 Flink 因为入湖速度较 Spark 慢,所以耗时稍多,但整体来看,Flink 已经能够满足日常修复需求。

未来展望

c384641e45e21e3698685b4fe75058ee.jpeg

我们的未来展望主要包括以下三点:

  • 基于 Iceberg 的秒级湖仓建设,目前 Flink+Iceberg 在我们内部实时链路中能够很好的支持分钟级的场景,我们希望未来在实时性上有所突破,将链路新鲜度提升至秒级。

  • 基于 Iceberg 的完整 CDC 的支持。目前,如果一张 Iceberg 被多个上游并行写入,或者单个作业回溯写入,我们需要使用 Upsert 模式,写入+I 或+U 前默认写入一条-D,但因为缺少信息,写入的 Delete 可能是多余的且无法获取到正确的非主键列值,我们希望在后期能够对其完善,使得下游能够读取到正确完整的 CDC 数据。

  • 跟进基于 Flink SQL Gateway,完善动态查询的支持。

往期精选

bc6aeebd45ccb6e3451af3a7c251096c.png

7da54508ebe710448d84c4f8a249d402.jpeg

b7d428e5a8a37c5bf568b64b9983b577.jpeg

8e673fd0a366f360379184030c4d0d3f.jpeg

9292a6a97a60fadb7ad72883a7262221.jpeg


▼ 活动推荐▼

4bd20df5489538a1708a44a5c6cb4f52.png

▼ 关注「Apache Flink」,获取更多技术干货 ▼

6593114cfa4e3d13ddbfd2491f94ad01.png

 412692419d01570a5557ab45b6b0bcca.gif  点击「阅读原文」,查看原文视频&演讲 PPT

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

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

相关文章

每每聊到线程Thread

进程和线程 进程 所谓计算机程序 Program,其实就是通过执行一系列指令来完成某一个任务。当你启动一个程序时,操作系统(OS)会将其加载到内存中,并在内存中申请一块固定地址的命名空间(address space),并在此命名空间内执行相关指令…

bert中文文本摘要代码(2)

bert中文文本摘要代码 写在最前面关于BERT使用transformers库进行微调 model.py自定义参数激活函数geluswish定义激活函数字典 BertConfig类参数配置vocab_size_or_config_json_filefrom_dict方法(from_json_file时调用)from_json_file方法一系列方法 Be…

Coursera自动驾驶2.1——最小二乘法和线性和非线性卡尔曼滤波

文章目录 一、最小二乘法1.最小二乘法2.加权最小二乘法3.递归最小二乘法4.最小二乘法与极大似然 二、卡尔曼滤波1.概述2.线性卡尔曼滤波3.扩展卡尔曼滤波Error State卡尔曼滤波 4.无迹卡尔曼滤波(1)无迹变换(2)无迹卡尔曼滤波 一、…

I.MX6ull 中断 一

一 I.MX6ull 中断介绍 1 中断类型 Cortex-A7内核有8个异常中断,这8个异常中断的中断向量表如下表所示: Cortex-A 内核 CPU 的所有外部中 断都属于这个 IRQ 中断,当任意一个外部中断发生的时候都会触发 IRQ 中断。在 IRQ 中断服 务函数里面就…

linux php8.2安装swoole扩展

下载swoole源码: wget https://wenda-1252906962.file.myqcloud.com/dist/swoole-src-5.0.2.tar.gz tar -zxvf swoole-src-5.0.2.tar.gz cd swoole-src-5.0.2/ 初始化: /www/server/php/82/bin/phpize 配置检查: ./configure --with-…

JDK17在Windows安装以及环境变量配置(超详细的教程)

目录 一、JDK17的安装包下载 二、安装JDK17 第一步:运行JDK的EXE文件 第二步:选择下一步 第三步:选择安装目录 第四步:安装完成 三、配置JDK17的环境变量 第一步:打开系统属性界面 第二步:打开高级…

C#,码海拾贝(31)——约化“对称矩阵“为“对称三对角阵“的“豪斯荷尔德Householder变换法“之C#源代码,《C#数值计算算法编程》源代码升级改进版

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 矩阵类 /// 作者&#xff1a;周长发 /// 改进&#xff1a;深度混淆 /// https://blog.csdn.net/beijinghorn /// </summary> public partial class Matrix {…

数据库信息速递 数据库基础设施已经不在青睐 ETL (译)

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

RabbitMq的高级特性--RabbitMQ高级特性_消息存活时间

RabbitMQ高级特性_消费端限流 &#xff0c; [解耦&#xff0c; 限流&#xff0c;降低压力&#xff0c;发送消息] 通过消费端限流的 方式限制消息的拉取速度&#xff0c;达到保护消费端的目的。 下面我们新建springboot项目进行测试&#xff1a; 新建项目myproducer 依赖&am…

chatgpt赋能python:Python关联算法:从数据挖掘到推荐系统

Python关联算法&#xff1a;从数据挖掘到推荐系统 Python编程语言已经成为各行各业中数据科学家和工程师的首选语言&#xff0c;其中包括处理数据集合的关联算法。 什么是关联算法&#xff1f; 数学上&#xff0c;关联算法是指在大型和复杂数据集合中&#xff0c; 寻找数据之…

干货 | 携程10个有效降低客户端超时的方法

作者简介 Wen&#xff0c;携程资深后端开发工程师&#xff0c;专注系统性能、稳定性、交易系统等领域。 一、背景 在现今的信息时代&#xff0c;微服务技术已成为一种重要的解决方案&#xff0c;微服务技术可以使系统的规模和功能变的更加灵活&#xff0c;从而获得更高的可扩展…

docker基本命令学习 | Docker网络、Docker镜像发布

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; docker安装、卸载 docker安装使用 卸载旧版本docker或者环境 [rootiZf8zdcobr3fw7vn0p3538Z /]# yum remove docker \ > docker-client \ >…

打破逢节降价桎梏!海尔智家:满足用户,全网第一

又是一年618&#xff0c;每到这个上半年最重要的消费节点&#xff0c;许多品牌卖家纷纷掀起价格战。 他们使出满减、满赠、满返等五花八门的策略&#xff0c;为了压制对手进行冲量&#xff0c;这也一度让“逢节降价”成为主流。 在市场天平偏向卖家的时代&#xff0c;这些策略…

SVN服务端visualsvn5.1.4下载安装(windows环境)(实操)

Apache Subversion 通常被缩写成 SVN&#xff0c;是一个开放源代码的版本控制系统&#xff0c;Subversion 在 2000 年由 CollabNet Inc 开发&#xff0c;现在发展成为 Apache 软件基金会的一个项目&#xff0c;同样是一个丰富的开发者和用户社区的一部分。 SVN相对于的RCS、CVS…

做自己喜欢的事

这两天沸沸扬扬的消息说稚辉君公司拿到了百度投资 稚晖君刚拿了百度投资&#xff0c;估值被曝已超独角兽 然后昨晚上小孩发烧&#xff0c;我陪床不敢死睡&#xff0c;跟大佬聊了下拿到投资的感受。 然后说到搞技术好玩这个事情&#xff0c;我就跟他分享了我前天到经历 我前天到…

Jenkins概念及安装配置教程(二)

如何安装Jenkins&#xff1f; Jenkins 安装程序也可以作为通用 Java 包 (.war) 使用。如果您将 Jenkins 与 Selenium 一起用于执行跨浏览器测试&#xff0c;我们建议使用 .war 文件&#xff0c;因为您可以通过在非无头模式下在浏览器上执行的自动化测试来见证测试场景的执行。…

【C# 10 和 .NET 6】使用MVC模式构建网站(笔记1)

Building Websites Using the Model-View-Controller Pattern 使用模型-视图-控制器模式构建网站 本章介绍使用 Microsoft ASP.NET Core MVC 在服务器端构建具有现代 HTTP 架构的网站&#xff0c;包括构成 ASP.NET Core MVC 项目的启动配置、身份验证、授权、路由、请求和响应管…

如何设计和使用文档模板 | 技术写作什么鬼

今天看到叶伟民老师的一篇文章&#xff0c;瞬间泪目&#xff1a;叶老师&#xff0c;您是懂人性的啊。在我整天鞭策自己“不能再拖了”的关键时刻&#xff0c;及时分享经验&#xff1a; 是的&#xff0c;这篇文章实在是拖了太久&#xff0c;了太久&#xff0c;太久&#xff0c;久…

web前端 --- javascript(03) -- 函数、内置对象

函数&#xff08;function&#xff09; 具有名称的&#xff0c;为了实现特定功能的代码集合体 &#xff08;1&#xff09;javascript如何定义函数&#xff1a;function关键字定义 function 函数名称 &#xff08;[ 参数列表 ]&#xff09;{ // 函数体 // [return 返回值]…

【Springboot】发送QQ邮件

系列文章目录 文章目录 系列文章目录前言添加Maven依赖QQ邮箱开启POP服务配置application.properties文件Controller层编写 vue前端&#xff08;也可以直接省略&#xff09; 前言 这篇博客用于简单实现SpringBoot中使用Controller发送邮件请求&#xff0c;用户可以收到邮件。 …