Apache Doris 在小鹅通的应用实践

峰会官网已上线,最新议程请关注doris-summit.org.cn 点击报名 先到先得

图片

本文导读:
随着网络直播规模的不断扩大,在线知识服务在直播行业中迎来了广阔的发展机遇。小鹅通作为一家以用户服务为核心的技术服务商,通过多平台直播与推流服务吸引和转化潜在用户,同时通过直播数据分析平台,帮助商家分析直播指标数据、分析用户观看情况、构建精准用户画像。然而,随着直播用户数量的激增,平台在写入和查询方面的支持逐渐无法满足业务需求,为了应对挑战,小鹅通开启了架构升级之旅。本文将详细介绍小鹅通直播数据分析平台的优化过程,分享小鹅通基于Apache Doris 优化写入与查询性能、完善用户标签功能和保障平台稳定性等实践经验,为商家提供了更精细化的用户经营支持

作者小鹅通 大数据开发工程师 宫贺

深圳小鹅网络技术有限公司,是一家以知识产品与用户服务为核心的技术服务商,创始至今已累计生产了 2000 万个知识产品,已服务的商家规模达 160 万,其中不乏腾讯学堂、华夏基金、西贝、吴晓波频道、十点读书、凯撒旅游等各行业一线知名品牌。作为私域运营的一站式工具,针对商家业务痛点,小鹅通提供了多方面的闭环解决方案,包括产品与服务交付、营销获客、用户运营、组织角色管理、品牌价值输出等以实现业务升级。

图片

随着“直播带货”消费模式的兴起,网络直播规模的持续上升,在线知识服务开始在直播行业中开拓广袤发展领域,借助直播工具的力量能够有效吸引和转化潜在用户,借助直播分析平台能够实现对 C 端用户数据留存与分析,助力 B 端商家客户的精细化用户运营。

在这一背景下,小鹅通直播为商家提供了多平台的直播与推流服务,以及多种直播带货的营销玩法,不仅能将公私域流量引导至直播间,实现商家引流目标,还提供了多维度的分析平台。商家可以通过直播数据分析平台导出和分析各项直播数据指标,生成用户标签,以了解用户观看直播的情况和动态、构建精准的用户画像。

目前,小鹅通直播场次已累积达 600 万次,终端用户数近 8 亿,最高同时在线观看人数超过 1000 万。然而,面对直播用户数量激增,直播数据分析平台在数据写、查方面的支持逐渐无法满足业务需求,我们希望能够借助分析平台掌握直播间在线人数、在线时长、商品转化率、交易额等数据,并在直播间波峰波谷时期记录以上数据的流量趋势图。为了满足上述的业务需求,小鹅通对于平台架构提出更高的性能要求:

  • 写入性能:需具备海量数据实时写入的能力,确保在直播过程中高吞吐场景下数据稳定导入;
  • 数据更新:为了应对直播期间交易状态和用户数据的变化,我们需要架构具备高效准确的更新机制,确保业务人员及时掌握最新数据;
  • 查询性能:能够支持高并发点查,也能满足联邦查询的需求,保证不同查询场景下数据分析的时效性;
  • 平台运维:由于直播业务具有明显的波峰波谷时段,分析平台需要确保在直播高峰时段保持稳定的运行状态。同时,在波谷时段,平台应该支持节点弹性缩容,以提高资源利用率并控制运维成本。此外,为了避免系统运行故障导致站点破坏、为了保持系统高可用性,架构还需要提供可靠的灾备方案,以确保业务连续。

在遭遇系统业务瓶颈后,小鹅通开启了平台基础建设重构之旅,在经过业务调研、选型对比和内测应用后,基于 Apache Doris 对最初 Elasticsearch 与 HBase 的架构进行了迭代升级,并于今年 5 月份正式上线 Apache Doris 版本的直播数据分析平台。

本文将详细介绍小鹅通直播数据分析平台的优化过程,分享小鹅通如何基于 Apache Doris 提升平台查询性能、完善用户标签功能、保障平台稳定性等实践经验,最终赋能商家精细化用户经营。

基于 Elasticsearch 与 HBase 早期架构


图片

直播数据分析平台的原始数据主要来源于 MySQL 的业务数据库、学习 SDK、埋点 SDK,平台架构主要分为离线与实时链路:

  • 离线链路:用户相关的数据通过 DataX 采集并全量存储于 HDFS ,由 Hive 计算写入 HBase,形成用户基本信息的主表。
  • 实时链路:MySQL 业务库与学习 SDK 中的相关指标数据(例如实时订阅、访问、直播互动、用户权益等)通过 Flink CDC 采集后上报至 Kafka,利用 Flink 实时计算并存入 Redis 中。

两类数据依据业务需求,将用户基本信息与直播相关业务指标关联,形成直播参与用户大宽表,其中当权益、订阅等主业务数据发生变更时,需要与 HBase 中的用户维表进行关联补全数据。数据每次更新都会在宽表补全后,将所有字段一起发送至下游 Elasticsearch 来承载业务人员的查询需求,避免并发修改的情况。

随着直播用户规模的扩大,我们对于数据时效性、查询性能等方面要求逐渐升高,而原架构的局限性也逐渐影响业务分析需求:

  • 数据流转时效性低:由于组件过多,导致计算链路过长、节点过多,写入与查询的时效性也必然会受到影响,无法支撑直播波峰时段的实时导入与极速分析。
  • 数据更新链路复杂:直播数据每次发生变更时,都需要先将变更数据写入主表与维度表中,随后重新关联生成新的宽表以覆盖旧数据。这一过程涉及多个组件和长链路,更新机制的复杂度与低效也随之增加。
  • 查询性能不足:在高并发查询场景下,Elasticsearch 需要处理大量的查询请求和数据访问,导致查询负载过重,分析效率低;在关联查询场景下,Elasticsearch 无法满足 Join 计算需求,查询灵活度低。
  • 架构运维成本高:组件过多还会导致整体架构运维成本升高、开发人员学习成本加大、指标扩展较为局限等问题。

基于以上架构痛点,我们在 2022 年 7 月开启系统重构项目的调研工作,最终在众多数据仓库中选择了 Apache Doris 进行架构升级,并在同年 11 月开启长达 6 个月的内测工作,希望借助 Apache Doris 在实时写入、数据高效更新、极速查询性能和简易运维等方面的优势,在直播数据分析场景中强化直播用户数据挖掘,获取更多高价值的业务洞察。

基于 Apache Doris 的全新直播数据分析平台


图片

在升级到全新架构后,我们统一了实时和离线两条数据处理链路,全部交由 Apache Doris 来进行处理。如图所示,原始数据经过 Flink 流处理计算后,会实时写入到 Apache Doris 的表模型中,根据场景我们分别选用了不同的数据模型进行查询加速,数据表与对应的查询需求具体如下:

  • 用户维度表:借助 Apache Doris 的 Aggregate Key 模型将用户维度数据聚合,同时通过 replace_if_not_null 方式实现部分列更新;
  • 标签表:为了更好地构建用户标签体系,实时更新用户画像,我们借助 Unique Key 将数据分为标签与标签版本两类表,通过 Merge on Write 更新数据,并借助 Doris 关联查询性能,使商家获取最新版本的用户标签。
  • 学习数据表:同样借助 Aggreagte Key 模型将用户在平台中的学习数据进行聚合,支持后续直播用户分析需求。

在 Apache Doris 引入后为我们提供了全新的数据流转,满足写入与查询时效性的需求,有效解决了原架构链路痛点。目前,我们基于 Doris 十余台集群规模为直播数据分析平台提供实时写入与极速分析,并带来了以下具体收益:

01 写查接口统一、写入效率更高

Flink-Doris-Connector 内置了 Flink CDC ,支持从业务数据库中全量和增量抽取数据,同时 Doris 也可以通过 Routine Load 来订阅 Kafka 中的数据、一流多表秒级写入,大幅提升了数据集成同步的效率。

利用 Apache Doris 替换原架构中 HBase 、Elasticsearch 等多个组件,减少了中间数据在不同链路中的流转,解决了链路过长、组件过多的问题,通过 Apache Doris 一套系统实现统一对外数据服务。

02 数据写时合并、高效更新

在 Apache Doris 聚合后,单表最大达数十亿的情况下,可以支撑每秒 20 万的数据 Upsert 与 Insert Overwrite,满足了直播高峰时期高吞吐写入需求。

在数据更新时,无需将字段补全后再重新开发宽表,可以直接利用 Merge On Write 功能进行轻量级 Merge,通过写时合并,实现微批高频实时写入与部分列更新。

03 多场景下的查询加速

在高并发点查时,我们高频使用 Doris 分区分桶裁剪功能,在查询时过滤非必要的数据,使数据扫描快速定位,加速查询响应时间。

在关联查询时,Apache Doris 支持对多张 10 亿级表进行 Join,满足分析人员将用户基础信息与学习、标签数据等关联查询需求。更重要的是,Doris 在标签检索、模糊查询、排序、分页等场景下都可以达到秒级甚至毫秒级的查询响应。

04 开发周期缩短、运维成本降低

Apache Doris 自身架构简单,FE 和 BE 两节点能够灵活扩缩容,易于部署、迁移与运维。在架构升级后,通过简化链路我们的运维成本相较于之前降低近 2/ 3。

同时 Doris 兼容 MySQL,使开发操作简单、使用门槛低,研发成本也随之降低。现在指标开发时间大幅度缩短,由原来单个指标耗时一个月缩短至现在仅需一周即可完成,加速指标迭代周期。

接下来,我们将从查询加速、容灾备份、数据可视化分析三方面分享 Apache Doris 在直播数据分析场景中应用实践,希望通过分享为读者提供更多关于 Doris 应用洞察。

用户画像场景查询加速实践


对于直播业务,用户标签是构成用户画像的核心因素,能够将用户在直播过程中所产生的行为数据分析提炼,生成具有差异性特征的标签词,以更好地掌握用户属性、用户偏好、直播习惯等信息。

在小鹅通直播分析平台中,商家可以自行定义规则生成标签,例如 “观看直播超过一分钟” 的用户为一类标签,“最近一分钟访问直播间”的用户为另一类标签。在这个过程中,商家会频繁不断地对用户“贴标签”(插入数据)或者“撕标签”(删减数据),与此同时每位用户也可能会存在多个自动或者手动标签。基于此,数仓需要具备以下能力:

  • 面对标签变动频繁的情况,数仓需要支持实时写入与更新,并保证集群稳定。
  • 面对同一用户的多类标签,数仓还需要提供强大的关联查询能力,并支持快速查询检索性能。

我们以下面的 SQL 为例,介绍基于 Apache Doris 在标签场景如何快速抽取数据、如何通过主键模型创建标签表与标签版本表、如何对字符串开启模糊查询解析,实现用户信息的快速检索,加速用户行为与经营业务分析。

创建标签表:

create table db.tags (  
u_id string,  
version string,  
tags string
) with (  
'connector' = 'doris',  
'fenodes' = '',  
'table.identifier' = 'tags',  
'username' = '',  
'password' = '',  
'sink.properties.format' = 'json',  
'sink.properties.strip_outer_array' = 'true',  
'sink.properties.fuzzy_parse' = 'true',  
'sink.properties.columns' = 'id,u_id,version,a_tags,m_tags,a_tags=bitmap_from_string(a_tags),m_tags=bitmap_from_string(m_tags)',  
'sink.batch.interval' = '10s',  
'sink.batch.size' = '100000' 
);

创建标签版本表:

create table db.tags_version (  
id string,  
u_id string,  
version string  
) with (  
'connector' = 'doris',  
'fenodes' = '',  
'table.identifier' = 'db.tags_version',  
'username' = '',  
'password' = '',  
'sink.properties.format' = 'json',  
'sink.properties.strip_outer_array' = 'true',  
'sink.properties.fuzzy_parse' = 'true',  
'sink.properties.columns' = 'id,u_id,version',  
'sink.batch.interval' = '10s',  
'sink.batch.size' = '100000'  
);

两类表写入:

insert into db.tags
select
u_id,  
last_timestamp as version,
tags
from db.source;  insert into rtime_db.tags_version
select 
u_id,  
last_timestamp as version
from db.source;

Bitmap 索引加速标签查询:

在写入完成后,业务人员开始对用户相关数据进行查询分析。以常见查询场景为例,我们需要查找某位姓张用户在最新版本中的标签数据,首先会在用户主表中使用 LIKE 匹配符合要求的用户名,其次在分页查询中对标签字段分别创建 Bitmap 索引,如 “123”、“124”、“125”、“126”、“333”,最后通过三表关联快速找到标签信息。

with t_user as (select u_id,namefrom db.userwhere partition_id = 1and name like '%张%'
),t_tags as (select u_id, versionfrom db.tagswhere (bitmap_and_count(a_tags, bitmap_from_string("123,124,125,126,333")) > 0 )),t_tag_version as (select id, u_id, versionfrom db.tags_version)select t1.u_idt1.name
from t_user t1
join t_tags t2 on t1.u_id = t2.u_id
join t_tag_version t3 on t2.u_id = t3.u_id and t2.version = t3.version
order by t1.u_id desc
limit 1,10;

在直播数亿用户规模、每位用户存在上千个标签的场景下,**使用 Bitmap 索引来查询用户相关数据后,查询时间均能够在 1 秒内响应并准确地为业务人员提供所需结果,**大大加速了标签查询速度。

双集群高可用方案


在直播课程大促期间,为了带动直播间的下单氛围,提升用户秒抢积极性与下单率,平台会在直播间开启抽奖等活动。在引入 Doris 之前,我们将每日备份数据到对象存储中。当直播过程中优惠券领取、下单等出现故障时,从用户反馈、层层上报,再到故障恢复,需要花费数个小时。

然而,在这数小时中,成百上千的用户会因此流失,我们则需要承受用户退出直播间、寻找其他替代产品等巨大风险与损失。因此,平台面对海量用户访问的冲击,数据恢复与解决故障的速度成为了直播间业务效益的关键。

为了保障短期指数级业务波峰下平台的稳定运行,我们决定采取全新容灾方案。基于 Apache Doris 主备双集群的方式,实现热备;使用 Airflow 通过 Backup 与 Freeze 策略将每日数据备份至对象存储,以实现冷备,其中热备具体流程如下:

  • 数据双写:改造 Flink Doris Connector,通过配置将数据写到两个集群或单个集群,在处理某个集群需要升级的场景时,先停止写一个集群后再去改造另外一个集群,有效保证集群的稳定性。
  • 负载均衡:通过反向代理来切换查询请求到指定集群。当某一集群出现了问题,我们可以及时把请求接到另外一个集群上面。
  • 监控校验:定期校验主从集群的数据及表结构的一致性,以便及时发现数据性不一致的情况。

我们还将进一步引入 Doris 2.0 版本中推出的 CCR 跨集群数据复制功能,尝试使用该功能减少开发运维成本,降低人工储备集群双写所导致两个集群 DDL 不一致的风险。

自研数据可视化平台,统一实时查询出口


图片

数据可视化分析平台主要用于离线报表、即席查询、实时数据大屏(Dashboard)三大场景,为商家业务人员、管理层等提供可视化分析功能。在引入 Doris 之后,我们将 MySQL、Elasticseach、本地文件等多种数据源统一交给 Apache Doris 实现。

同时,为了更好地将数据呈现给商家,我们还增加了数据源管理与数据集创建功能,业务人员可以直接在平台中选择数据源进行配置、测试等操作,形成可视化列表。除此之外,平台结合了 BI 工具中丰富的图表样式,满足商家配置数据看板的个性化需求。

在引入 Apache Doris 之后,通过数据集的配置实现了数据管理、权限管理等功能,并利用 Apache Doris 极速多维分析、联邦查询的能力加速了数字化平台的查询展示性能,摒弃了原来的 T+1 报表,在 Apache Doris 之上实现即时查询。

未来规划


目前,基于 Apache Doris 构建的分析平台主要用于小鹅通直播业务,为用户相关数据提供服务。在 Apache Doris 引入后,平台架构实现了写查出口统一、时效性大幅提升、用户数据多维分析场景拓展,同时 Doris 的加持还使后台系统具备稳定性、可扩展性、安全性等关键优势。这些突破促使平台基础技术能力进一步提高,也促进了用户数量、直播效益进一步增长。

后续我们希望继续拓展 Apache Doris 的使用场景,将课程分析、用户日志分析等交由 Apache Doris 对外提供统一的数据分析服务。同时,我们也希望继续探索 Apache Doris 2.0 版本的新特性,进一步提升集群稳定性能,包括:

  • Pipeline 执行引擎和基于成本的查询优化器:在做用户直播列表时有许多复杂的售后场景需要人工优化,当有了 Pipeline 执行引擎和查询优化器后,不再需要人工调 SQL ,使执行性能更优;
  • CCR 跨集群数据同步:通过用户多集群的数据库表自动同步以提升在线服务数据的可用性;
  • 倒排索引:利用 Apache Doris 2.0 版本的倒排索引功能,对现有的索引结构进行丰富,实现模糊查询、等值查询和范围查询等能力,进一步加速查询响应速度。

在此特别感谢 SelectDB 技术团队在使用过程中遇到任何问题都能及时响应,为我们降低了许多试错成本。未来,我们也会更积极参与 Apache Doris 社区贡献及活动,与社区共同进步和成长!

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

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

相关文章

简单实现一个todoList(上移、下移、置顶、置底)

演示 html部分 <!DOCTYPE html> <html> <head><title>表格示例</title> </head> <body><table border"1"><thead><tr><th>更新时间</th><th>操作</th></tr></thead…

2023-10-12 LeetCode每日一题(找出数组的串联值)

2023-10-12每日一题 一、题目编号 2562. 找出数组的串联值二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的整数数组 nums 。 现定义两个数字的 串联 是由这两个数值串联起来形成的新数字。 例如&#xff0c;15 和 49 的串联是 1549 。 nums 的 串…

BootStrap-前端框架

资料:https://v3.bootcss.com/components/ BootStrap的概念&#xff08;Web框架&#xff09; Bootstrap&#xff0c;来自 Twitter&#xff0c;是目前很受欢迎的前端框架。Bootstrap 是基于 HTML、CSS、JavaScript 的&#xff0c;它简洁灵活&#xff0c;使得 Web 开发更加快捷。…

给电瓶车“消消火”——TSINGSEE青犀智能电瓶车棚监控方案

近年来&#xff0c;电瓶车电梯起火、室内起火、楼道起火的新闻层出不穷&#xff0c;很多人为了图方便就将电瓶车推到家中充电&#xff0c;这种十分危险的行为&#xff0c;严重影响了社区的公共安全和个人生命财产&#xff0c;为什么惨痛新闻不断播出&#xff0c;这种行为还是屡…

el-dialog两个弹框里面套弹框受外层弹框影响

el-dialog嵌套的影响及解决方法 解决方法如下&#xff1a; 在里层弹框里添加 append-to-body <el-dialogtitle"图片预览":visible.sync"dialogVisible"class"imgDialog":modal"false"append-to-body><img width"100%&q…

nodejs+vue电子病历管理系统

过软件的需求分析已经获得了系统的基本功能需求&#xff0c;根据需求&#xff0c;将电子病历管理系统功能模块主要分为管理员模块。管理员添加科室信息管理、项目分类管理、药品分类管理、公告信息管理、用户管理等操作。 本系统结合计算机系统的结构、概念、模型、原理、方法&…

LiveMedia视频中间件视频隐私打码直播解决方案

一、方案背景 随着科技的发展&#xff0c;视频监控系统已经成为了我们生活中不可或缺的一部分。无论是在公共区域&#xff0c;还是在私人场所&#xff0c;我们都可以看到各种各样的监控设备。这些设备的出现&#xff0c;无疑提高了我们的生活安全&#xff0c;使得我们可以更好地…

cas-server5.3自定义密码校验规则

前面几篇文章都是关于cas的,今天继续,cas有自己的一个加密配置.如果只是简单使用MD5或者SM3等加密算法进行加密的话,可以不需要再进行自定义操作,但是我们一般还会给用户密码加盐,这样的话原本的配置就不满足了,所以需要再自定义一个密码校验规则 实现PasswordEncoder接口 Pa…

Swagger3.0 与spring boot2.7x 整合避免swagger2.0与boot2.7冲突

注释掉2.0引入的俩包 直接引入3.0 <dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version></dependency> swagger配置文件粘贴即用哦 import org.springfram…

linux 给根目录扩容(lvm CentOS 7.6 kylinx86)

问题:Linux系统挂载到根目录的磁盘空间满了,如何扩容? 用命令:lsblk 可以查看磁盘和分区情况,可以发现磁盘vda下面的还有大部分空间没有使用。 操作步骤 1、使用 fdisk -l 查看硬盘序号,并用 fdisk 对硬盘操作,格式化成lvm的格式 (用命令lsblk可以看到,挂载到根目录…

ppt怎么压缩到10m以内?分享ppt缩小方法

在日常工作中&#xff0c;我们常常需要制作和分享PowerPoint演示文稿&#xff0c;然而&#xff0c;有时候文稿中的图片、视频等元素会导致文件过大&#xff0c;无法在电子邮件或其他平台上顺利传输。为了将PPT文件压缩到10M以内&#xff0c;我们可以使用一些专门的文件压缩工具…

SQL sever中的索引

目录 一、索引定义 二、索引结构 2.1. B-树索引结构&#xff1a; 2.2. 哈希索引结构&#xff1a; 三、索引作用 四、索引与约束区别 五、索引级别 六、索引分类 6.1. 聚集索引&#xff08;Clustered Index&#xff09;&#xff1a; 6.2. 非聚集索引&#xff08;Noncl…

PyQt5 PyQt6 Designer 的安装

pip国内的一些镜像 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 豆瓣(douban) http://pypi.douban.com/simple/ 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/ 中国科学技术大学 http://pypi.mirrors.ustc.…

Open Winding-PMSM-开绕组永磁同步电机基本介绍

文章目录 前言简介Open Widing电机数学模型零序模型 双逆变器调制零序电流抑制基本思路 前言 最近看了些Open Winding永磁同步电机及其控制策略的文献资料&#xff0c;现做个总结。未来的研究方向也大概率围绕Open Winding开展&#xff0c;期待同行交流学习。 简介 开绕组(O…

互联网Java工程师面试题·Java 并发编程篇·第三弹

目录 26、什么是线程组&#xff0c;为什么在 Java 中不推荐使用&#xff1f; 27、为什么使用 Executor 框架比使用应用创建和管理线程好&#xff1f; 27.1 为什么要使用 Executor 线程池框架 27.2 使用 Executor 线程池框架的优点 28、java 中有几种方法可以实现一个线程…

【java学习—七】单继承和多层继承(30)

文章目录 1. 相关概念2. 从代码中理解 1. 相关概念 Java 只支持单继承&#xff0c;不允许多重继承&#xff1a; &#xff08;1&#xff09;一个子类只能有一个父类 &#xff08;2&#xff09;一个父类可以派生出多个子类      举例区分&#xff1a; class SubDemo extend…

【大数据】Hadoop MapReduce与Hadoop YARN(学习笔记)

一、Hadoop MapReduce介绍 1、设计构思 1&#xff09;如何对付大数据处理场景 对相互间不具有计算依赖关系的大数据计算任务&#xff0c;实现并行最自然的办法就是采取MapReduce分而治之的策略。 不可拆分的计算任务或相互间有依赖关系的数据无法进行并行计算&#xff01; …

OCP Java17 SE Developers 复习题05

答案 答案 A, E. Instance and static variables can be marked final, making option A correct. Effectively final means a local variable is not marked final but whose value does not change after it is set, making option B incorrect. Option C is incorrect, a…

ideal远程Debug部署在服务器上的服务详解

ideal远程Debug部署在服务器上的服务详解 一 简介二 ideal配置步骤第一步&#xff1a;点击Edit Configurations选项添加远程连接第二步&#xff1a;配置Remote JVM debug参数第三步&#xff1a;服务的启动参数中添加第二步生成的命令并重新启动服务第四步&#xff1a;ideal启动…

Linux 部署 GitLab idea 连接

概述 GitLab 是一个开源的代码管理平台&#xff0c;使用 Git 作为版本控制工具&#xff0c;提供了 Web 界面和多种功能&#xff0c;如 wiki、issue 跟踪、CI/CD 等。 GitLab 可以自托管或使用 SaaS 服务&#xff0c;支持多种操作系统和执行器。 GitLab 可以帮助软件开发团队…