小红书湖仓架构的跃迁之路

news2025/3/1 19:01:17

作者:李鹏霖(丁典),小红书-研发工程师,StarRocks Contributor & Apache Impala Committer

本文整理自小红书工程师在 StarRocks 年度峰会上的分享,介绍了小红书自助分析平台中,StarRocks 与 Iceberg 结合后,如何实现极速湖仓分析架构。

与原有架构相比,湖上分析架构的 P90 查询性能提升了 3 倍,目前查询 响应时间 稳定在 10 秒以内。 同时,采用 Iceberg 存储格式后,尽管数据量和行数保持不变,但实际存储空间相较原有 ClickHouse 存算分离版本减少了一半。

RedBI 自助分析是小红书数据平台下的一款可视化、即席查询分析工具,专为分析师设计。它支持通过简单的拖拽操作完成数据分析,并在秒级返回查询结果,核心特点可以总结为: 灵活、快速、自助

下图为自助分析平台的原始架构,其核心是小红书内部自研存算分离版本的 ClickHouse。通过存算分离和智能缓存,不仅延长了数据集的生命周期,还能根据业务使用习惯将热点数据缓存在本地,从而实现接近存算一体架构的查询性能。

在数据分析流程中,分析师首先与数据仓库团队讨论数据需求。根据需求,数据仓库团队会创建相应的数据集,并在小红书的大数据研发管理平台 Dataverse 上开发 Hive2CK 类型的 ETL 任务。

Hive2CK 任务 是一种基于 Spark 的数据处理任务,主要从上游的 Hive 表中获取数据。处理后的数据会先写入 OSS(对象存储服务),然后通过 ClickHouse 将这些文件加载至其系统中,根据用户的使用习惯将热点数据缓存至本地,确保最终提供给用户查询。

原架构痛点

首先,随着业务需求的快速增长和分析师使用习惯的不断变化,最初基于与数据仓库团队沟通制定的索引策略逐渐失效,导致数据集的查询性能出现明显下降。现有架构没有灵活的机制来根据分析需求和使用习惯动态调整排序键与索引,因此导致 查询性能下降

其次,ClickHouse 在支持 Join 操作方面存在一定限制。尽管可以为部分数据集建立 Colocate Join,但其桶数与集群节点绑定的方式,使得扩容或缩容时,节点数和桶数之间的依赖关系增加了操作复杂度。此外,维度表无法复用,Join Key 的绑定程度过高,使得不同数据集之间的 Join 操作灵活性受限。

最后,数据的访问方式也存在一定局限。目前的数据访问只能通过 ClickHouse 查询,缺乏更灵活的方式,尤其在一些场景下,某些数据需要根据不同的分析需求进行读取。如果继续依赖 ClickHouse 来读取这些数据,可能会对线上服务产生影响,导致系统在处理多样化需求时,性能和效率遭遇瓶颈。

这些问题不仅影响了查询性能,也限制了平台的扩展性和自助性,迫切需要找到一套有效的解决方案来应对当前架构的挑战。

湖上分析架构

随着原架构暴露出的性能瓶颈和灵活性限制,我们开始寻求更加高效的解决方案。在此背景下,RedBI 自助分析平台的架构进行了重大升级,采用了新的湖上分析架构。

首先,原有的 Hive2CK 替换为 Hive2Iceberg,数据存储格式转为 Parquet。与 ClickHouse 存储格式相比,这种转变不仅在支持各自最优压缩算法的前提下,实现了更高的压缩率, 实际应用中的压缩比提升了近一倍 。此外,StarRocks 作为 OLAP 查询引擎,具备了出色的扩缩容能力和快速的响应速度。

与此同时,依托 StarRocks 的 DataCache 功能,查询性能不再依赖于网卡 I/O。通过将热点数据缓存至本地 BE 节点,避免了频繁的远程数据拉取,进一步提升了查询的稳定性和响应速度。

在年初立项前,我们对湖上分析架构进行了 POC 测试。测试集选取了当时自助分析中排名前十的热门数据集,并模拟了 N 天内的实际查询场景。测试结果表明,与原有架构相比, 湖上分析架构的 P90 查询性能实现了 3 倍的提升。

排序键 保鲜能力

为了应对随着时间推移数据集查询性能下降的问题,我们设计了一套湖上分析数据集智能优化的解决方案。

  • 扩展 StarRocks 的审计日志插件,新增了 Iceberg ScanReport 的关键信息(如 nonPartFilterCols、resultDataFiles 和 dataInBytes)。

  • 结合审计日志数据与表统计信息,预估用户的使用习惯,智能选择排序列。

  • 针对新增分区数据,通过异步 ZOrder 排序任务优化非分区列的 DataSkip 效果,从而实现排序键和索引的持续优化。

提升数据集的自助性

针对多表分析场景(如自助分析人群包维表和笔记维表),当前,分析平台采用了 Broadcast Join / InSubQuery 的方式进行处理,这相较于传统的 Colocate Join 具有显著的性能优势。由于 Broadcast Join 不依赖于节点绑定,它使得扩容与缩容变得更加灵活,能够根据业务需求动态调整,而不受固定节点数的限制。

为了进一步提升数据集的自助性,我们引入了灵活配置的 JoinKey 策略。原则上,只要能够避免数据倾斜,任何字段都可作为 JoinKey。不过,考虑到当前集群规模与平台性能要求,我们对可进行 Shuffle Join 的维表数量做出了限制,最多支持与主表进行关联的 四个维表 ,以避免影响其他数据集的快速响应。

取数灵活

湖上数据集的存储与查询完全分离,赋予了更高的灵活性。用户可以直接通过 SQL 在公共 OLAP 资源池中进行启发式和探索式查询,既满足了多样化需求,又避免了对特定引擎或集群的依赖。

Data Skipping

  1. 关于排序的优化:

当我们在 DLF (Data Lake Formation)中检测到大部分拖拽查询都集中在某一列时,可以采用 线性排序 来提升效率。而对于两列或三列的场景,可以进一步考虑多维排序。需要注意的是,排序列通常不会超过三列,这样既能保证查询性能,又避免了复杂度过高的问题。

  1. Z-Order排序:

Z-Order(也称为Z-Order Curve)是一种空间填充曲线,用于将多维数据映射到一维数据中。Z-Order 本质上是一种对多维数据进行排序的方式,它通过将多个维度的坐标交替地排列在一起,从而形成一个线性索引。

Z-Order 通过将数据点在多维空间中的坐标进行交替二进制编码,然后根据这些编码来排序。例如,在二维空间中,假设一个点有两个维度(x, y),我们可以将 x 和 y 的二进制位交替排列,形成一个新的值。对于更高维度的数据,Z-Order 会扩展此方法。在二维情况下,如果一个点的坐标是 (x, y),而 x 和 y 的二进制表示分别为:

  • x = 3 → 011

  • y = 5 → 101

那么,Z-Order 会将这两个二进制值交替取各位形成成:

  • z = 0, 1, 1, 0, 1, 1

Z-Order 的关键在于它可以对多维数据进行有效的线性排序,这种排序在某些查询模式下具有很好的性能表现,尤其是范围查询。

  1. DataFile ( Parquet file)非分区列 min-max 索引

Iceberg 具备“DataFile(Parquet 文件)非分区列的 Min-Max 索引”功能,具体表现为:

  • 无需打开具体的 Parquet 文件,用户即可通过 Iceberg 元数据访问该索引。

  • 在经过上述排序后,Parquet 文件内部数据将呈现有序结构。结合 Min-Max 索引特性,Iceberg 能在前端(FE)执行谓词下推,从而显著提升数据湖分析的性能。

上图展示了 Iceberg 的整体结构,元数据文件中的 ManifestFile 包含了大量 DataFile 级别的指标,例如:

DataFile.RECORD_COUNT,
DataFile.FILE_SIZE,
DataFile.COLUMN_SIZES,
DataFile.VALUE_COUNTS,
DataFile.NULL_VALUE_COUNTS,
DataFile.NAN_VALUE_COUNTS,
DataFile.LOWER_BOUNDS,
DataFile.UPPER_BOUNDS,
...

有了全部 DataFile 中非分区列的 min-max 索引数据,就可以做谓词下推。在 OLAP 引擎创建查询计划时,通过 org.apache.iceberg.Scan#planFiles 接口,根据 WHERE 子句中的谓词和 min-max 索引数据进行 DataFiles 级别的过滤,从而显著提升查询性能。

参考:

https://github.com/apache/iceberg/blob/main/api/src/main/java/org/apache/iceberg/TableScan.java

https://github.com/apache/iceberg/blob/main/api/src/main/java/org/apache/iceberg/DataFile.java

智能选择 Z-Order 排序键

为解决 ClickHouse 索引键保鲜度较低 的问题,我们设计了一种基于用户行为记录的智能排序键选择与更新机制,应用于 自助分析平台 ,并通过 Z-Order 排序 提升查询效率。上图红框展示了这一机制的核心流程。

具体实现步骤如下:

  1. StarRocks 审计日志插件: 记录每个查询中每个表的下推的非分区列信息,以及 planFiles 接口返回的迭代器中涉及的 DataFiles 总 Bytes 等信息。

  2. 数据湖管理平台 (DLF): 通过分析审计日志,智能推断出自助分析数据集中的表的候选排序列。根据这些列的NDV(不同值数量)做一层筛选,最终系统会自动在 Dataverse 平台创建和更新rewrite_zorder_dataFiles 任务。

  3. Dataverse 平台 :具有任务血缘能力,确保在上游 hive2iceberg 任务完成后,自动触发 rewrite_zorder_dataFiles 任务。

  4. 异步执行: rewrite_zorder_dataFiles 任务的执行是异步的,依赖于 Iceberg 的原子提交(atomiccommit)机制,分析师用户不感知整个优化过程。

StarRocks x Iceberg JOIN

在自助分析场景中,用户对数据集自助性的需求不断提升,尤其是在 JoinKey 灵活选择 上。StarRocks 支持成熟的 Shuffle JoinBroadcast Join 能力,不受分桶数或集群节点扩缩容的影响,能够快速扩展原数据集的 JoinKey。用户只需审批通过,即可在 分钟级 内完成新 JoinKey 的上线配置。

在项目中期阶段,湖上数据集的覆盖率已经达到 50%。然而,由于大多数数据集是从 ClickHouse 迁移而来的单表数据,且当时机型无法满足 DataCache 的使用需求,分析任务仍依赖从 OSS 读取 Parquet 文件。这种情况下,随着用户需求从单表分析转向多表数据集配置,Shuffle Join 的使用频率激增,网卡带宽逐渐成为性能瓶颈。

为解决这一问题,我们首先针对规模较大的多表数据集,选择采用 Iceberg 分桶表(10 桶) 的方式优化数据分布。同时,在 StarRocks 中引入对 Iceberg 分桶表的 Colocate Join 和 Bucket Join 支持,减少 Shuffle Join 对网卡带宽的依赖,从而缓解性能压力。在这一阶段,我们优先缓解网卡带宽瓶颈,待机型满足要求后,再逐步引入 DataCache ,通过本地磁盘读取替代从 OSS 读取数据的方式。

随着 DataCache 的引入,网卡带宽几乎完全腾出来用于 Shuffle Join 和 Broadcast Join,这不仅提升了性能,也保留了对 JoinKey 的灵活扩展能力。即使在使用分桶表时,仍能够兼顾 Shuffle Join 的扩展性,无需考虑集群节点数量的问题, 提高数据集自主性

排序列选取算法

在数据湖管理平台中,为提升查询性能和优化数据存储结构,排序列的筛选显得尤为重要。以下是排序列选取算法的具体规则和条件:

  1. 唯一值数量 (NDV)

排序列的候选字段需要具备足够的区分度。因此,算法会筛选唯一值数量(NDV)不少于 15 的列,以避免因低区分度而导致的排序效果较差。

  1. 频次比例

某列的查询使用频率,即列的使用次数与该表的查询总次数的比值,应不少于 0.15。这一条件确保排序列是用户查询的核心字段,有助于优化高频使用场景。

  1. 文件数量

数据分区中文件数量的丰富性是影响排序效果的另一个因素。候选列所在的分区,文件数量应超过 10 个,以确保排序后的数据能覆盖更多文件。

  1. 频次排名

为进一步提高排序列的筛选精度,算法优先关注查询频次排名前 3 的列。这种方式能够快速锁定用户最常查询的字段,最大化排序优化的收益。

  1. 查询占比

最后,通过分析列在整体查询中的占比,判断其是否值得进行排序。如果某列的查询占比较低,即便符合其他条件,也可能会被排除在排序列之外,从而避免无效优化。

查询性能优化

Data Skip 效果

随着业务需求的变化,某流量占比较高的数据集经历了多轮迭代和扩展。从最初包含店铺 ID、用户 ID、商品 ID 等基本字段,到逐步加入直播间 ID 和用户浏览笔记 ID 等信息,该数据集的字段不断丰富以满足日益复杂的分析需求。

为了应对这种动态变化,我们通过调整 Z-Order 排序任务中的排序列(sort_order),实现对数据的动态优化。具体来说,根据分析师的使用习惯和 T+1 阶段反馈,及时调整排序方式,使得新增数据可以更贴近近期用户的查询模式。值得注意的是,这一优化完全异步进行,不会影响历史数据,用户也无需感知优化过程即可受益。

优化完成后,该数据集的某些常用查询模式显著受益,占整体查询的比例达到 30%。从优化后的统计图表可以看到,Data Skip 技术在减少数据扫描量上效果明显,当前每日扫描数据量与优化后的 Data Skip 数据量形成了鲜明对比。

Data Cache

在数据湖分析场景中,StarRocks作为OLAP查询引擎,需要高效地扫描存储在对象存储(如OSS)中的 Parquet 文件。以小红书自助分析平台为例,频繁访问相同的数据会导致重复的网络I/O开销,尤其是在数据是 T+1 产出时。此时,带宽资源往往不能充分用于多表数据集的Join操作。为了优化这一问题,StarRocks 自 2.5 版本引入了 DataCache 功能。

StarRocks DataCache 通过将外部存储系统中的原始数据切分成多个数据块,并将这些块缓存到StarRocks本地的BE节点,从而减少了重复的远程数据拉取开销。这样,热点数据可以被缓存到本地,显著提升了查询和分析的性能。根据测试数据, 集群的 P90 查询性能提升约 20% 。需要注意的是,缓存的块位置与节点数量紧密相关。当集群进行扩缩容操作时,部分缓存会失效,导致一些数据块不再有效。

为了解决扩缩容后缓存失效的问题,当前的解决办法是安排在夜间进行扩缩容,并在扩缩容完成后重新运行当天的查询。这样,数据缓存会重新分布,并确保缓存的有效性。这一策略保证了在集群扩缩容后,DataCache功能能够快速恢复。

在我们的实际场景中,针对线上的两个典型查询案例进行了分析,截取了查询的执行Profile,结果显示,DataCache的命中率相当高,几乎达到理想状态。这个效果的原因主要有以下几点:

首先,由于数据集大多属于T+1级别的数据,上午生成的数据在下午一般不会发生变化。这样一来,用户查询的数据集基本保持一致,查询模式趋于稳定。这种情况下,DataCache能够高效缓存热点数据,减少了重复的数据拉取,显著提升了查询性能。

其次,每天的查询习惯大致相同,尤其是同一天内,用户查询的需求往往会集中在相似的时间段和数据范围。因此,数据缓存策略能够在用户查询峰值时,提供足够的缓存支持,从而减少了带宽消耗,并加速了查询响应。

通过对比开启和关闭DataCache时的监控数据,我们可以在Grafana中清晰地看到,开启DataCache后,网卡流量显著降低,节省的带宽几乎达到了2到3倍。

大查询优化策略

在面对大查询带来的性能瓶颈时,我们实施了大查询优化策略,以确保自助分析平台能够在数据量激增的情况下,继续保持高效的查询响应能力。

随着某些业务的快速增长,新数据分区的数量急剧增加,导致某些查询涉及的单个分区数据量大幅上升。例如,某些数据集的单分区数据量从年初的100亿,已经增长至目前的200多亿。这种数据量的增长可能会导致查询过慢,甚至影响系统的整体性能,特别是在没有有效优化的情况下。

为了应对这一挑战,我们为StarRocks中的Iceberg表实现了 EXPLAIN ESTIMATE 功能。该功能能够在实际查询之前估算查询的数据量。如果预估结果显示查询的数据量超过某个设定的阈值,系统会智能地将查询请求引导到一个规模较小的StarRocks集群,或者是Spark集群来执行,从而避免超大查询占用过多计算资源。这不仅减少了对其他查询的影响,也降低了查询超时的风险。

从性能监控数据来看,开启此优化功能后,整体集群的CPU使用率得到了有效控制。特别是在大查询出现时,CPU的负载没有急剧攀升,避免了计算资源的过度消耗。相对而言,P90响应时间在开启该优化后表现更为平稳,避免了因资源过载而导致的性能急剧下降。

项目收益

根据我们的测量结果,从年初到现在, P90 响应时间提升了三倍,当前的查询响应时间大约可以控制在10秒以内

此外,通过优化存储方式,尤其是应用Iceberg的Parquet存储格式(如版本1.12),我们在存储效率上也获得了显著的提升。与原有的ClickHouse存量分离版本相比,采用Iceberg存储后,尽管数据量和行数保持一致, 但实际存储空间减少了一半

未来规划

未来规划中,我们将探索结合 StarRocks 和 Paimon 的近实时湖仓分析架构,围绕公司业务需求,进一步优化近实时链路的处理能力,并针对具有主键(PK)需求的湖上分析场景,制定更高效的优化方案。

直播回放:https://www.bilibili.com/video/BV18EC5YuEcA/?vd_source=1cb452610138142d1300dd37a6162a88

延伸阅读:

StarRocks 助力小红书离线数仓提效,提升百倍回刷性能!

StarRocks 在小红书自助分析场景的应用与实践

更多交流,联系我们:StarRocks

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

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

相关文章

C++-第十七章:包装器

目录 第一节:std::function 第二节:std::bind 2-1.基本介绍 2-2.调整顺序(不常用) 2-3.调整个数 2-4.std::bind与std::function 下期预告: C中有3种可调用对象:函数指针、仿函数对象、lambda函数,经过包装器包装后屏…

TCP的三次握手与四次挥手:建立与终止连接的关键步骤

引言 ‌TCP(传输控制协议)工作在OSI模型的传输层‌。OSI模型将计算机网络功能划分为七个层级,从底层到顶层依次是:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。传输层负责在网络节点之间提供可靠的端到端通信&a…

2025计算机考研复试资料(附:网课+历年复试真题+140所高校真题+机试)

目录 2025 计算机考研复试经验全攻略,附超全资源🎁 (一)网课资源 (二)历年复试真题 (三)140 所高校真题 二、专业知识复习篇 (一)复试专业课程 二&…

Milvus高性能向量数据库与大模型结合

Milvus | 高性能向量数据库,为规模而构建Milvus 是一个为 GenAI 应用构建的开源向量数据库。使用 pip 安装,执行高速搜索,并扩展到数十亿个向量。https://milvus.io/zh Milvus 是什么? Milvus 是一种高性能、高扩展性的向量数据…

腾讯游戏完成架构调整 IEG新设五大产品事业部

易采游戏网2月28日独家消息:继1月份腾讯天美工作室群完成内部组织架构调整后,腾讯旗下互动娱乐事业群(IEG)再次宣布对组织架构进行优化调整。此次调整的核心在于新设立了五大产品事业部,包括体育产品部、音舞产品部、V…

达梦数据库系列之安装及Mysql数据迁移

达梦数据库系列之安装及Mysql数据迁移 1. 达梦数据库1.1 简介1.2 Docker安装达梦1.2.1 默认密码查询1.2.2 docker启动指定密码 1.3 达梦数据库连接工具1.3.1 快捷键 2 Mysql数据库迁移至达梦2.1 使用SQLark进行数据迁移 1. 达梦数据库 1.1 简介 DM8是达梦公司在总结DM系列产品…

java jar包内的jar包如何打补丁

问题描述: 主包:hisca.jar,解压后 BOOT-INFO/lib下有其他jar包 因为一个小bug,需要修改这个hisca包下BOOT-INF/lib下的子jar包service-hisca-impl-1.0.0.jar中的一个service类及xml文件 操作步骤: 1、主包jar -xvf …

【企业场景】上线的项目如何进行限流

一、常见的四种速率限流算法 对于限流,最为直接的就是速率限流了 固定窗口算法 比如 10r/s 就是把时间线分为 1s 一段,也就是周期为 1s,对一个时间段的请求进行计数,超过 10 则舍弃,未超过则直接处理经过 1s 后&…

git - study

文章目录 git - study概述可以用 git gui工具来添加快捷命令工具如果要在提交日志中搜索,可以用gitk的view编辑功能实验环境直接用git自带环境进行git操作的好处查看git所有配置配置全局数据配置项目专用的数据查询配置数据的原始值配置git使用的文本编辑器获取某个…

FPGA之硬件设计笔记-持续更新中

目录 1、说在前面2、FPGA硬件设计总计说明3、 原理图详解 - ARITX - 7 系列3.1 顶层框图介绍3.2 FPGA 电源sheet介绍:3.2.1 bank 14 和 bank 15的供电3.2.2 bank 0的供电3.2.3 Bank34 35 的供电 3.3 核电压和RAM电压以及辅助电压 4 原理图详解-- Ultrascale ARTIX4.…

嵌入式开发:傅里叶变换(5):STM32和Matlab联调验证FFT

目录 1. MATLAB获取 STM32 的原始数据 2. 将数据上传到电脑 3. MATLAB 接收数据并验证 STM32进行傅里叶代码 结果分析 STM32 和 MATLAB 联调是嵌入式开发中常见的工作流程,通常目的是将 STM32 采集的数据或控制信号传输到 MATLAB 中进行实时处理、分析和可视化…

Cursor AI编程-详细教程

一点准备工作 Cursor方法论:简单到没有方法 Cursor能做什么 Cursor官网:https://www.cursor.com/ja Cursor文档:Cursor – Welcome to Cursor Cursor论坛:Weekly - Cursor - Community Forum 写程序代码 举例: 设…

(十 三)趣学设计模式 之 模版方法模式!

目录 一、 啥是模板方法模式?二、 为什么要用模板方法模式?三、 模板方法模式的实现方式四、 模板方法模式的优缺点五、 模板方法模式的应用场景六、 总结 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式&a…

泛型编程、函数模板、类模板

目录 一、泛型编程 1.泛型编程提出背景 1.1.代码复用案例解析 案例1:实现一个交换函数,并对不同类型参数进行函数重载 (1)调试 (2)代码解析 ①代码复用问题 ②泛型编程的解决方案 ③上面泛型Swap函数模版的优点 1.2.泛型编程提出背景 2.泛型编…

【Vue3】浅谈setup语法糖

Vue3 的 setup 语法糖是通过 <script setup> 标签启用的特性&#xff0c;它是对 Composition API 的进一步封装&#xff0c;旨在简化组件的声明式写法&#xff0c;同时保留 Composition API 的逻辑组织能力。以下是其核心概念和原理分析&#xff1a; 一、<script setu…

简洁的个人地址发布页HTML源码

源码介绍 简洁的个人地址发布页HTML源码,源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果 效果预览 源码获取 简洁的个人地址发布页HTML源码

wav格式的音频压缩,WAV 转 MP3 VBR 体积缩减比为 13.5%、多个 MP3 格式音频合并为一个、文件夹存在则删除重建,不存在则直接建立

&#x1f947; 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 &#x1f389; 声明: 作为全网 AI 领域 干货最多的博主之一&#xff0c;❤️ 不负光阴不负卿 ❤️ 文章目录 问题一&#xff1a;wav格式的音频压缩为哪些格式&#xff0c;网络传输给用户播放…

Linux权限 -- 开发工具(一)

文章目录 包管理器yumyum具体操作 Linux编辑器 - vim的使用vimvim的多模式 包管理器yum Linux中安装软件&#xff1a; 1.源码安装 2. 软件包安装 – rpm 3. 包管理器yum(centos) apt/apt-get(ubuntu) 为什么有包管理器&#xff1f; 包管理器会自动帮我们解决包依赖的问题 2. 什…

【leetcode】二分查找专题

文章目录 1.二分查找1.题目2.解题思路3. 解题代码 2.在排序数组中查找元素的第一个和最后一个位置1.题目2.算法原理3. 代码 3.x的平方根1.题目2.代码 4.搜索插入位置1.题目2.解题思路3.解题代码 5.山脉数组的索引1.题目2.解题思路3. 代码 6.寻找峰值1.题目2.解题思路3.代码 7. …

《Python实战进阶》No 7: 一个AI大模型聊天室的构建-基于WebSocket 实时通信开发实战

第7集&#xff1a; 一个AI大模型聊天室的构建-基于WebSocket 实时通信开发实战 在现代 Web 开发中&#xff0c;实时通信已经成为许多应用的核心需求。无论是聊天应用、股票行情推送&#xff0c;还是多人协作工具&#xff0c;WebSocket 都是实现高效实时通信的最佳选择之一。本…