Trip.com 如何从 Elasticsearch 迁移到 ClickHouse 并构建了 50PB 的日志解决方案

news2024/11/16 9:45:42

图片

本文字数:8721;估计阅读时间:22 分钟

审校:庄晓东(魏庄)

本文在公众号【ClickHouseInc】首发

图片

在 Trip.com,我们为用户提供广泛的数字产品,包括酒店和机票预订、景点、旅游套餐、商务旅行管理和与旅行相关的内容。正如你所猜的那样,我们需要一个可扩展、可靠且快速的日志平台,这对于我们的运营至关重要。

在我们开始之前,为了激起你的好奇心,让我展示一些我们在 ClickHouse 上构建的平台的关键数据:

图片

这篇博客文章将讲述我们日志平台的故事,包括为什么我们最初构建它、我们使用的技术,以及我们在 ClickHouse 上利用 SharedMergeTree 等功能对其未来的规划。

以下是我们在旅程中将讨论的不同主题:

  • 我们如何构建一个集中的日志平台

  • 我们如何扩展日志平台并从 Elasticsearch 迁移到 ClickHouse

  • 我们如何改进我们的运营体验

  • 我们如何在阿里云上测试 ClickHouse Cloud

为了简化,让我们把这些内容放在一个时间线上:

图片

构建一个集中的日志平台

每个伟大的故事都始于一个巨大的挑战。在我们的案例中,这个项目起源于 2012 年之前,因为 Trip.com 没有统一或集中的日志平台。每个团队和业务单元(BU)各自收集和管理自己的日志,这带来了许多不同的问题:

  • 需要大量人力来开发、维护和操作所有这些环境,不可避免地导致了大量重复工作。

  • 数据治理和控制变得复杂。

  • 公司内部没有统一的标准。

基于这些问题,我们意识到需要构建一个集中和统一的日志平台。

2012 年,我们推出了第一个平台。它建立在 Elasticsearch 之上,开始定义 ETL、存储、日志访问和查询的标准。

尽管我们不再使用 Elasticsearch 作为我们的日志平台,但值得探讨我们当初是如何实现这个解决方案的。它驱动了我们后来的许多工作,这是我们在后续迁移到 ClickHouse 时必须考虑的。

存储

我们的 Elasticsearch 集群主要由主控节点、协调节点和数据节点组成。

主控节点

每个 Elasticsearch 集群至少由三个主控节点组成。其中一个将被选为主节点,负责维护集群状态。集群状态是包含有关各种索引、分片、副本等信息的元数据。任何修改集群状态的操作都会由主控节点执行。

数据节点

数据节点存储数据并用于执行增删改查(CRUD)操作。它们可以分为多个层次:热层、暖层等。

协调节点

这种类型的节点没有其他功能(如主控、数据、摄取、转换等),并通过考虑集群状态作为智能负载均衡器。如果协调节点接收到带有 CRUD 操作的查询,它会被发送到数据节点。相反,如果接收到添加或删除索引的查询,它会被发送到主控节点。

图片

可视化

基于 Elasticsearch 我们使用 Kibana 作为可视化层。你可以在下方看到一个可视化示例:

图片

日志插入

我们的用户有两种方式将日志发送到平台:通过 Kafka 和通过代理。

通过 Kafka

第一种方法是使用公司的框架 TripLog 将数据导入 Kafka 消息代理(使用 Hermes)。


private static final Logger log = LoggerFactory.getLogger(Demo.class);

public void demo (){
  TagMarker marker = TagMarkerBuilder.newBuilder().scenario("demo").addTag("tagA", "valueA").addTag("tagA", "valueA").build();
  log.info(marker, "Hello World!");
}

这为用户提供了一个轻松将日志发送到平台的框架。

通过代理工具

另一种方法是使用代理工具,如 Filebeat、Logstash、Logagent 或定制客户端,直接写入 Kafka。你可以在下面看到一个 Filebeat 配置示例:


filebeat.config.inputs:
  enabled: true
  path: "/path/to/your/filebeat/config"
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/history.log
      - /var/log/auth.log
      - /var/log/secure
      - /var/log/messages
    harvester_buffer_size: 102400
    max_bytes: 100000
    tail_files: true
    fields:
      type: os
    ignore_older: 30m
    close_inactive: 2m
    close_timeout: 40m
    close_removed: true
    clean_removed: true
output.kafka:
  hosts: ["kafka_broker1", "kafka_broker2"]
  topic: "logs-%{[fields.type]}"
  required_acks: 0
  compression: none
  max_message_bytes: 1000000
processors:
  - rename:
      when:
        equals:
          source: "message"
          target: "log_message"

​​​​​​​

ETL

无论用户选择哪种方法,数据最终都会进入 Kafka,然后可以通过 gohangout 管道传输到 Elasticsearch。

Gohangout 是由 trip.com 开发和维护的开源应用程序,作为 Logstash 的替代方案。它旨在从 Kafka 获取数据,执行 ETL 操作,最终将数据输出到各种存储介质中,如 ClickHouse 和 Elasticsearch。Filter 模块中的数据处理包括常见的数据清洗功能,如 JSON 处理、Grok 模式匹配和时间转换(如下所示)。在下面的示例中,GoHangout 使用正则表达式匹配从 Message 字段提取 num 数据,并将其存储为单独的字段。

图片

达到瓶颈

许多人使用 Elasticsearch 进行可观测性,在处理较小数据量时表现出色。它提供易于使用的软件、无模式体验、广泛的功能和流行的 Kibana 界面。然而,当我们这种大规模部署时,它存在一些众所周知的挑战。

当我们在 Elasticsearch 中存储 4PB 数据时,我们开始面临集群稳定性的多个问题:

  1. 集群上的高负载导致许多请求被拒绝、写入延迟和查询缓慢

  2. 每日将 200 TB 数据从热节点迁移到冷节点导致显著的性能下降

  3. 分片分配是一个挑战,导致一些节点过载

  4. 大查询导致内存不足 (OOM) 异常

关于集群性能

  1. 查询速度受到整体集群状态的影响

  2. 由于摄取过程中高 CPU 使用率,我们难以提高插入吞吐量

最后,关于成本

  1. 数据量大、数据结构复杂且缺乏压缩导致需要大量存储空间

  2. 较弱的压缩率对业务产生影响,迫使我们缩短保留期

  3. Elasticsearch 的 JVM 和内存限制导致更高的 TCO(总体拥有成本)

所以,在意识到以上所有问题后,我们寻找替代方案,于是 ClickHouse 出现了!

ClickHouse vs Elasticsearch

Elasticsearch 和 ClickHouse 之间存在一些基本差异;让我们来看看它们。

查询 DSL vs SQL

Elasticsearch 依赖于一种特定的查询语言,称为查询 DSL(领域专用语言)。尽管现在有更多的选项,但这仍然是主要语法。另一方面,ClickHouse 依赖于 SQL,这是一种非常主流且非常用户友好的语言,并且与许多不同的集成和 BI 工具兼容。

内部机制

Elasticsearch 和 ClickHouse 在内部行为上有一些相似之处,Elasticsearch 生成段,而 ClickHouse 写入部分。虽然两者都会随着时间的推移异步合并,创建更大的部分和段,但 ClickHouse 通过列式模型区分自己,其中数据通过 ORDER BY 键排序。这允许构建稀疏索引,从而实现快速过滤和高效的存储使用,因为压缩率很高。你可以在这篇出色的指南中了解更多关于此索引机制的信息。

索引 vs 表

Elasticsearch 中的数据存储在索引中,并分解为分片。这些需要保持在相对较小的大小范围内(在我们使用时,推荐的是大约 50GB 的分片)。相比之下,ClickHouse 的数据存储在显著更大的表中(在 TB 范围内,如果不受磁盘大小限制的话,还可以更大)。除此之外,ClickHouse 允许你创建分区键,这会将数据物理上分隔到不同的文件夹中。如果需要,可以高效地操作这些分区。

总体而言,我们对 ClickHouse 的功能和特性印象深刻:它的列式存储、向量化查询执行、高压缩率和高插入吞吐量。这些满足了我们对日志解决方案在性能、稳定性和成本效益方面的需求。因此,我们决定使用 ClickHouse 来替换我们的存储和查询层。

下一个挑战是如何无缝地从一种存储迁移到另一种存储而不中断服务。

日志平台 2.0:迁移到 ClickHouse

在决定迁移到 ClickHouse 之后,我们确定了需要完成的几个任务:

图片

表设计

这是我们当时确定的初始表设计(请记住,那是几年前的事了,当时 ClickHouse 还没有现在的所有数据类型,例如 maps):


CREATE TABLE log.example
(
  `timestamp` DateTime64(9) CODEC(ZSTD(1)),
  `_log_increment_id` Int64 CODEC(ZSTD(1)),
  `host_ip` LowCardinality(String) CODEC(ZSTD(1)),
  `host_name` LowCardinality(String) CODEC(ZSTD(1)),
  `log_level` LowCardinality(String) CODEC(ZSTD(1)),
  `message` String CODEC(ZSTD(1)),
  `message_prefix` String MATERIALIZED substring(message, 1, 128) CODEC(ZSTD(1)),
  `_tag_keys` Array(LowCardinality(String)) CODEC(ZSTD(1)),
  `_tag_vals` Array(String) CODEC(ZSTD(1)),
  `log_type` LowCardinality(String) CODEC(ZSTD(1)),
   ...
   INDEX idx_message_prefix message_prefix TYPE tokenbf_v1(8192, 2, 0) GRANULARITY 16,
   ...
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/example', '{replica}')
PARTITION BY toYYYYMMDD(timestamp)
ORDER BY (log_level, timestamp, host_ip, host_name)
TTL toDateTime(timestamp) + toIntervalHour(168)
  • 我们使用双数组方法来存储动态变化的标签(我们计划未来使用 maps),即有两个数组分别存储键和值。

  • 按天分区以便于数据操作。对于我们的数据量,每日分区是合适的,但大多数情况下,较高的粒度如每月或每周更好。

  • 根据你在查询中使用的过滤器,你可能希望有一个与上表不同的 ORDER BY 键。上面的键是针对使用 log_level 时间的查询进行优化的。例如,如果你的查询不使用 log_level,那么在键中只包含时间列是有意义的。

  • Tokenbf_v1 布隆过滤器用于优化关键词查询和模糊查询。

  • _log_increment_id 列包含一个全局唯一的增量 ID,以实现高效的滚动分页和精确的数据定位。

  • ZSTD 数据压缩方法,节省了超过 40% 的存储成本。

集群设置

鉴于我们在 Elasticsearch 上的历史设置和经验,我们决定复制一个相似的架构。我们的 ClickHouse-Keeper 实例充当主节点(类似于 Elasticsearch)。部署了多查询节点,这些节点不存储数据,而是持有指向 ClickHouse 服务器的分布式表。这些服务器托管数据节点,存储和写入数据。以下显示了我们最终的架构:

图片

数据可视化

在迁移到 ClickHouse 后,我们希望为用户提供无缝体验。为此,我们需要确保所有的可视化和仪表板都能使用 ClickHouse。这带来了一个挑战,因为 Kibana 是一个最初在 Elasticsearch 上开发的工具,不支持其他存储引擎。因此,我们必须对其进行自定义,以确保它能够与 ClickHouse 接口。这需要我们在 Kibana 中创建新的数据面板,可以与 ClickHouse 一起使用:chhistogramchhitschpercentileschrangeschstatschtablechterms 和 chuniq

然后,我们创建了脚本,将 95% 的现有 Kibana 仪表板迁移到使用 ClickHouse。最后,我们增强了 Kibana,使用户可以编写 SQL 查询。

图片

Triplog

我们的日志管道是自助服务,允许用户发送日志。这些用户需要能够创建索引并定义所有权、权限和 TTL 策略。因此,我们创建了一个名为 Triplog 的平台,为用户提供管理表、用户和角色的接口,监控其数据流,并创建警报。

图片

回顾

现在一切都已迁移完毕,是时候看看我们平台的新性能了!尽管我们自动化了 95% 的迁移并实现了无缝过渡,但回顾我们的成功指标并查看新平台的表现仍然很重要。两个最重要的指标是查询性能和总体拥有成本(TCO)。

TCO

我们最初成本的一个重要组成部分是存储。让我们比较一下 Elasticsearch 和 ClickHouse 在相同数据样本上的存储情况:

图片

存储空间节省超过 50%,使现有的 Elasticsearch 服务器能够支持 4 倍的数据量增加。

查询性能

图片

查询速度比 Elasticsearch 快 4 到 30 倍,P90 小于 300 毫秒,P99 小于 1.5 秒。

日志 3.0:改进基于 ClickHouse 的平台

自从我们在 2022 年完成从 Elasticsearch 的迁移以来,我们在平台上增加了更多日志用例,使其从 4PB 增长到 20PB。随着它继续增长并扩展到 30PB,我们遇到了新的挑战。

性能和功能瓶颈

  1. 在这种规模下管理单个 ClickHouse 集群是具有挑战性的。在部署时,没有 ClickHouse-Keeper 或 SharedMergeTree,我们面临着 Zookeeper 的性能瓶颈,导致 DDL 超时异常。

  2. 用户的不良索引选择导致查询性能不佳,需要使用更好的模式重新插入数据。

  3. 未优化的查询导致性能问题。

操作挑战

  1. 集群构建依赖于 Ansible,导致长部署周期(数小时)。

  2. 我们当前的 ClickHouse 实例版本落后于社区版本,当前的集群部署模式不便于进行更新。

为了解决上述性能挑战,我们首先放弃了单集群的架构。在我们的规模下,没有 SharedMergeTree 和 ClickHouse Keeper,元数据的管理变得困难,由于 Zookeeper 的瓶颈,我们会遇到 DDL 语句的超时问题。因此,我们创建了多个集群,而不是保留一个单一的集群,如下所示:

图片

这种新架构帮助我们扩展并克服了 Zookeeper 的限制。我们将这些集群部署到 Kubernetes,使用 StatefulSets、反亲和和 ConfigMaps。这将单个集群的交付时间从 2 天减少到 5 分钟。同时,我们标准化了部署架构,简化了全球多个环境中的部署流程。这种方法显著降低了我们的运营成本,并有助于实施上述方法。

查询路由

尽管上述方案解决了一些挑战,但它引入了新的复杂性,即如何将用户的查询路由到特定的集群。

让我们举个例子来说明:

假设我们有三个集群:集群1、集群2和集群3,以及三个表:A、B和C。在我们实施下面描述的虚拟表分区方法之前,一个表(如A)只能存在于一个数据集群中(例如集群1)。这种设计限制意味着当集群1的磁盘空间用满时,我们没有快速的方法将表A的数据迁移到集群2的空闲磁盘空间。相反,我们不得不使用双写操作,同时将表A的数据写入集群1和集群2。然后,在集群2中的数据过期后(例如七天后),我们可以从集群1中删除表A的数据。这个过程繁琐且缓慢,需要大量手动工作来管理集群。

图片

为了解决这个问题,我们设计了一个类似类的分区架构,使表A能够在多个集群(集群1、集群2和集群3)之间来回移动。如右侧所示,转换后,表A的数据基于时间间隔进行分区(可以精确到秒,但这里为了简单起见使用天作为例子)。例如,6月8日的数据写入集群1,6月9日的数据写入集群2,6月10日的数据写入集群3。当查询命中6月8日的数据时,我们只查询集群1的数据。当查询需要6月9日和10日的数据时,我们同时查询集群2和集群3的数据。

我们通过建立不同的分布式表实现了这一功能,每个分布式表表示特定时间段的数据,并且与多个集群(如集群1、集群2和集群3)的逻辑组合相关联。这种方法解决了跨集群表的问题,使不同集群之间的磁盘使用更加平衡。

图片

如上图所示,每个查询会根据其 WHERE 子句由代理智能重定向到包含所需表的正确集群。

这种架构有助于模式的演变。由于可以添加和删除列,有些表可以有更多或更少的列。上述路由可以在列级别应用,代理可以过滤不包含查询所需列的表。

此外,这种架构帮助我们支持演变的 ORDER BY 键——通常在 ClickHouse 中,无法动态更改表的 ORDER BY 键。通过上述方法,你只需更改新表上的 ORDER BY 键,并让旧表过期(得益于 TTL)。

Antlr4 SQL 解析

在查询层,我们使用 Antlr4 技术将用户的 SQL 查询解析为抽象语法树(AST)。通过 AST 树,我们可以快速获取 SQL 查询中的表名、过滤条件和聚合维度等信息。利用这些信息,我们可以轻松实现针对 SQL 查询的实时策略,例如数据统计、查询重写和流量控制。

图片

我们为所有用户的 SQL 查询实现了一个统一的查询网关代理。该程序基于元数据信息和策略重写用户的 SQL 查询,实现精确路由和自动性能优化等功能。此外,它记录了每个查询的详细上下文,用于统一管理集群查询,限制 QPS、大表扫描和查询执行时间,从而提高系统稳定性。

我们平台的未来是什么?

我们的平台在 40PB+ 规模下已经得到验证,但仍有许多需要改进的地方。我们希望能够更加动态地扩展,以便在假期等高峰期间更优雅地应对高峰需求。为了应对这种扩展需求,我们开始探索 ClickHouse 企业服务(通过阿里云),引入了 SharedMergeTree 表引擎。这一新架构提供了存储和计算的原生分离。通过这种新架构,我们可以提供几乎无限的存储,以支持 trip.com 内部更多的日志用例。

阿里云上提供的 ClickHouse 企业服务与 ClickHouse Cloud 使用相同版本的 ClickHouse。

在阿里云上测试 ClickHouse 企业服务

为了测试 ClickHouse 企业服务,我们首先将数据双写,插入到现有部署和利用 SharedMergeTree 的新服务中。为了模拟真实的工作负载,我们:

  • 将 3TB 数据加载到两个集群中,然后继续插入负载。

  • 收集各种查询模板用作测试集。

  • 使用脚本构建查询,这些查询将在特定值保证非空结果集的情况下查询随机的 1 小时时间间隔。

关于使用的基础设施:

  • 3 个节点,每个节点 32 个 CPU 和 128 GiB 内存,使用对象存储用于 ClickHouse 企业版(带 SMT)

  • 2 个节点,每个节点 40 个 CPU 和 176 GiB 内存,使用 HDD 用于社区版(开源)

为了执行我们的查询工作负载,我们使用了 clickhouse-benchmark 工具(ClickHouse 自带)对两种服务进行测试。

  1. 企业版和社区版都配置为使用文件系统缓存,因为我们希望重现生产环境的条件(生产环境中数据量更大,缓存命中率较低)

  2. 我们将以 2 的并发运行第一次测试,每个查询执行 3 次。

Testing RoundP50P90P99P9999Avg
Alicloud Enterprise Edition1st0.260.627.222.990.67
2nd0.240.464.420.610.52
3rd0.240.4816.7521.710.70
Avg0.246
40.3%
0.52
22.2%
7.05
71.4%
21.77
90.3
0.63
51.6%
Alicloud Community Edition1st0.633.411.0629.501.39
2nd0.641.929.3523.501.20
3rd0.581.609.2319.31.07
Avg0.61
100%
2.31
100%
9.88
100%
24.1
100%
1.07
100%

ClickHouse 企业服务的结果显示为黄色,阿里云社区版的结果显示为红色。相对于社区版的性能百分比显示为绿色(越低越好)。

随着并发增加,社区版很快无法处理工作负载并开始返回错误。这实际上意味着企业版能够有效地处理三倍的并发查询。

尽管 ClickHouse 企业服务使用对象存储作为数据存储方式,但它在高并发工作负载方面表现更好。我们认为这种无缝的就地升级可以大大减轻我们的运营负担。

因此,我们决定开始将业务指标迁移到企业服务。这包括支付完成率、订单统计等信息。我们建议所有社区用户试用企业服务!

征稿启示

面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com

图片

​​联系我们

手机号:13910395701

邮箱:Tracy.Wang@clickhouse.com

满足您所有的在线分析列式数据库管理需求

 

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

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

相关文章

玩个游戏 找以下2个wordpress外贸主题的不同 你几找到几处

Aitken艾特肯wordpress外贸主题 适合中国产品出海的蓝色风格wordpress外贸主题,产品多图展示、可自定义显示产品详细参数。 https://www.jianzhanpress.com/?p7060 Ultra奥创工业装备公司wordpress主题 蓝色风格wordpress主题,适合装备制造、工业设备…

红酒达人教你秘技:选酒、存酒,一招一式皆学问

在繁忙的都市生活中,红酒不仅仅是一种饮品,更是一种生活态度,一种品味的象征。然而,面对琳琅满目的红酒品牌与种类,如何选择一瓶心仪的红酒,又如何妥善保存,使其保持很好口感,成为了…

数据库字段不区分大小写

如果你的数据库也是这个排序规则,那么就没法区分大小写。常用的是这样的建表语句。它的collate已经声明为ci(不区分大小写) 这个时候你Cao和cao当作条件去查询其实作用是一样的,查出来的东西一模一样。 想要区分也很简单&#xff…

Web 权限管理最佳实践:如何提升用户满意度与应用安全性?

引言 在当今数字化时代,Web应用的功能和复杂性不断增加,用户对在线服务的期望也在不断提升。为了提供丰富的用户体验,许多Web应用需要访问用户的个人信息或设备功能,如地理位置、摄像头和麦克风等。这些权限访问在提升应用功能的…

倾斜摄影OSGB一键轻量化输出3dTiles!

老子云为打通OSGB应用通路,研发了OSGB格式一键转换3dTiles技术服务,通过轻量化操作即可快速实现格式间的转换,并且转换后模型可直接使用amrt展示框架加载、二次开发深度应用,此项服务已在平台上线,欢迎用户体验。接下来…

38 - 换座位(高频 SQL 50 题基础版)

38 - 换座位 -- 方法一 select(casewhen id%21 and id(select max(id) from seat) then idwhen id%20 then id-1else id1end) as id, student fromseat order byid;-- 方法二selectif(id%20,id-1,if(id(select max(id) from Seat),id,id1)) as id,student fromSeat order by id…

Ant Design Vue Upload 自定义上传 customRequest,这一篇很详细

Upload 常用属性和方法 示例上传接口 # 接口文档 url https://www.mocky.io/api/main/upload 头部 x-token: xxx 参数 file: File // 上传的文件 flag: xxx // 上传的标识// 文件上传 api 函数简单封装 export const uploadApi ({ file }) > {const formData new Fo…

Java医院绩效考核系统源码 :3分钟带你了解(医院绩效考核系统有哪些应用场景)三级公立医院绩效考核系统源码

Java医院绩效考核系统源码 :3分钟带你了解(医院绩效考核系统有哪些应用场景)三级公立医院绩效考核系统源码 作为医院用综合绩效核算系统,系统需要和his系统进行对接,按照设定周期,从his系统获取医院科室和…

2024系统分析师考试总结

考试缘由 我自己在毕业不久就考过了中级的软件设计师,这几年换到外企后事情不多,今年初定计划的时候就想着不如考个系统分析师吧。为什么选这个类别呢?按道理我主做程序开发,如果去考系统架构师通过率可能会大一些,但…

深度神经网络(dnn)--风格迁移(简单易懂)

概括 深度神经网络(DNN)在风格迁移领域的应用,实现了将一幅图像的艺术风格迁移到另一幅图像上的目标。该技术基于深度学习模型,特别是卷积神经网络(CNN),通过提取内容图像的内容特征和风格图像的…

JAVA应用开发和.net应用开发可以一起学吗?

JAVA应用开发和.NET应用开发同时学习是可行的,但需要记住几个关键点,以确保学习效率和理解深度。刚好我有一些资料,是我根据网友给的问题精心整理了一份「JAVA的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信…

uniapp横屏移动端卡片缩进轮播图

uniapp横屏移动端卡片缩进轮播图 效果&#xff1a; 代码&#xff1a; <!-- 简单封装轮播图组件:swiperCard --> <template><swiper class"swiper" circular :indicator-dots"true" :autoplay"true" :interval"10000&quo…

JAVA小知识29:IO流(上)

IO流是指在计算机中进行输入和输出操作的一种方式&#xff0c;用于读取和写入数据。IO流主要用于处理数据传输&#xff0c;可以将数据从一个地方传送到另一个地方&#xff0c;例如从内存到硬盘&#xff0c;从网络到内存等。IO流在编程中非常常见&#xff0c;特别是在文件操作和…

Git的安装配置及使用(超详细!!!)

一、git概述 它是一个版本管理工具. 版本: 软件开发过程当中的重要节点. 作用: 团队协作,管理代码. 对于软件的学习, 会用就行. 1.1 安装及配置 下载地址: github.com 安装注意事项: 傻瓜式安装,一直下一步就好. 安装目录不要有中文. 尽量也不要有空格. 配置环境变量: 找到…

1亿参数的细胞大模型来了!登Nature子刊,清华大学团队发布scFoundation:对2万基因同时建模

近年来&#xff0c;大规模预训练模型正在引领新一轮人工智能浪潮。「大模型」通过从大规模、多来源的数据中提取深层次规律&#xff0c;进而能够作为「基础模型」服务不同领域的多样化任务。例如&#xff0c;大语言模型通过学习大量文本数据&#xff0c;掌握了理解和识别语言的…

Python 列表去重方法解析与使用详解

概要 在 Python 编程中,列表是非常常用的数据结构之一。由于在实际使用中,我们经常会遇到包含重复元素的列表,因此对列表进行去重操作是一个常见的需求。本文将详细介绍多种 Python 列表去重的方法,并提供相应的示例代码,帮助更好地掌握这些技术。 使用集合(set) 集合…

充电桩现场安装施工流程

摘要&#xff1a;在化石能源日益紧缩的今天&#xff0c;新能源车辆逐渐走进了千家万户&#xff0c;与传统化石能源车辆相比&#xff0c;以电驱动的新能源车辆能源利用率高&#xff0c;缩短了能源传递过程&#xff0c;实现了能源有效利用。根据能量守恒定律可知&#xff0c;任何…

一文读懂RSTP流媒体传输原理

什么是流&#xff1f; 流&#xff08;Streaming&#xff09;&#xff1a;近年在Internet上出现的新概念&#xff0c;定义非常广泛&#xff0c;主要是指通过网络传输多媒体数据的技术总称。 流式传输分为两种&#xff1a;顺序流式传输 (Progressive Streaming)和实时流式传输 (R…

2024挣大钱的机会来了!入职这一行,也能“一飞冲天”

不知不觉我们已经走过了疫情笼罩的三年。如今&#xff0c;已经全面放开&#xff0c;自12月起核酸检测也将彻底取消&#xff0c;对于我们每个人来说这也将是一场长期的战役。 然而在疫情的常态化下&#xff0c;国民经济也将逐渐恢复。对于我们普通人来说如何抓住机遇&#xff…

【渗透测试】小程序反编译

前言 在渗透测试时&#xff0c;除了常规的Web渗透&#xff0c;小程序也是我们需要重点关注的地方&#xff0c;微信小程序反编译后&#xff0c;可以借助微信小程序开发者工具进行调试&#xff0c;搜索敏感关键字&#xff0c;或许能够发现泄露的AccessKey等敏感信息及数据 工具…