文章目录

  • 一、LSM树的设计哲学:写优化的根本动机
    • 1、 传统B+树存储的性能瓶颈
    • 2、 LSM树的根本性创新
  • 二、写入路径的深度技术分析
    • 1、 WAL机制的精密设计
    • 2、 MemTable的数据结构
    • 3、 刷盘(Flush)过程的技术细节
  • 三、Compaction策略:LSM树性能优化的核心机制
    • 1、为什么LSM树必须要Compaction?LSM树设计带来的必然问题
    • 2、Compaction理论
      • 2.1、Compaction概念
      • 2.2、写放大的产生机制
      • 2.3、分层架构的设计智慧
    • 3、Size-Tiered与Leveled:两种哲学的对比
      • 3.1 Size-Tiered的简洁哲学
      • 3.2 策略选择的智慧
    • 4、Compaction的本质与价值
  • 四、 LSM树读取路径:从简单写入到复杂查询
    • 1. 为什么LSM树的读取比写入复杂?
    • 2. Bloom Filter:LSM树读取优化的核心武器
  • 五、LSM树性能特性:三个核心权衡
    • 1、写放大、读放大、空间放大的本质
    • 2、不同存储介质的性能影响
  • 六、LSM树的工程实践:监控与恢复的核心机制
    • 1、为什么LSM树需要特殊的监控策略?
    • 2、WAL:LSM树可靠性的保险机制

LSM树(Log-Structured Merge Tree)作为现代分布式数据库的核心存储引擎,其设计哲学体现了对写入密集型工作负载的深度优化。从Cassandra到RocksDB,从HBase到TiKV,LSM树已成为大规模分布式系统的标准选择。本文将深入剖析LSM树的技术内核,探讨其设计权衡与工程实践。

一、LSM树的设计哲学:写优化的根本动机

1、 传统B+树存储的性能瓶颈

传统的B+树存储结构在写入密集型场景下面临根本性挑战。B+树的 就地更新(In-Place Update) 特性要求写入操作直接修改磁盘上的数据页,这导致了几个严重问题:

  1. 随机I/O的性能陷阱:
    B+树的写入往往涉及随机磁盘访问。当插入新数据时,需要找到对应的叶子节点,可能触发节点分裂,进而影响父节点。这些操作在磁盘上通常是不连续的,导致大量随机I/O
    机械硬盘的随机I/O性能通常只有100-200 IOPS,而顺序I/O可以达到100MB/s以上。即使在SSD上,随机I/O的性能也远低于顺序I/O。这种性能差异在高并发写入场景下被放大,成为系统瓶颈。

  2. 写放大问题的累积效应:
    B+树的修改经常需要 重写整个数据页,即使只修改其中的一条记录 。更严重的是,如果修改导致页分裂,可能需要更新多个页面。这种**写放大(Write Amplification)**现象在SSD上尤其有害,会显著降低SSD的使用寿命。

  3. 并发控制的复杂性:
    就地更新要求复杂的锁机制来保证并发安全。多个写入操作可能需要锁定相同的页面,导致锁竞争和等待。这种竞争在高并发场景下会严重影响系统吞吐量。

 

2、 LSM树的根本性创新

LSM树通过追加写入(Append-Only) 的设计哲学从根本上解决了上述问题:

  1. 顺序I/O的性能优势:
    所有写入操作都转换为顺序追加,无论是WAL的写入还是SSTable的生成,都充分利用了磁盘的顺序I/O性能。这种设计使得LSM树在机械硬盘上也能获得优异的写入性能。

  2. 写放大的控制:
    虽然LSM树在Compaction过程中也存在写放大,但这种放大是可控制和可预测的。通过调整Compaction策略,可以在写放大和读性能之间找到最佳平衡点。

  3. 无锁并发的简化:
    追加写入的特性使得LSM树可以采用更简单的并发控制机制。内存中的MemTable可以使用高效的无锁数据结构,磁盘上的SSTable是不可变的,天然支持并发读取。

 

二、写入路径的深度技术分析

1、 WAL机制的精密设计

WAL(Write-Ahead Log)不仅仅是简单的日志文件,其设计涉及多个精密的技术考量:

a. 日志格式的优化:

WAL的日志格式需要在空间效率和解析速度之间平衡。典型的WAL记录包含:记录类型、时间戳、键值对、校验和等信息。通过紧凑的二进制格式和高效的编码算法,可以最小化WAL的存储开销。

 

b. 批量写入的聚合策略:

单条记录的WAL写入效率很低,因为每次写入都需要系统调用。现代LSM实现通常采用批量写入聚合策略:将多个写入操作的WAL记录合并到一个批次中,减少系统调用次数。

但批量大小的选择需要权衡:更大的批量可以提高吞吐量,但会增加延迟和内存使用。通常采用动态调整策略,根据当前的写入负载自动调整批量大小

 

c. 同步策略的选择:

WAL的持久化同步策略直接影响性能和可靠性:

  • 每次同步(sync on every write):最高可靠性,但性能较低
  • 定时同步(periodic sync):在可靠性和性能之间平衡
  • 异步同步(async sync):最高性能,但存在数据丢失风险

大多数系统提供可配置的同步策略,允许用户根据业务需求选择。

 

d. 日志回收的复杂性:

WAL文件会随着写入不断增长,需要及时回收以避免磁盘空间耗尽。但日志回收必须确保安全性:只有当对应的MemTable已经成功刷盘后,才能删除相应的WAL段。

这需要精确的元数据管理来跟踪每个WAL段对应的MemTable状态。在系统故障恢复时,需要确保所有未刷盘的WAL段都能被正确replay。

 

2、 MemTable的数据结构

MemTable是LSM树的内存写入缓冲区,将随机写入转换为有序存储,然后批量刷盘。

写入流程

阶段状态作用
Active可写接收新写入,支持查询
Immutable只读停止写入,准备刷盘
Flushed回收数据已写入磁盘,释放内存

数据结构选择:跳表。为什么选择跳表?

  • 并发友好:支持无锁操作,避免锁竞争
  • 有序性:天然维护键值有序,便于刷盘和范围查询
  • 实现简单:相比红黑树等复杂结构,更容易实现和调试

优缺点分析

优势说明
高写入性能内存操作,延迟极低
有序存储为后续磁盘写入提供有序数据
并发友好支持高并发读写操作
劣势说明
内存限制受内存大小约束,需及时刷盘
数据丢失风险系统崩溃时内存数据丢失(需WAL保护)
查询复杂性读取时需同时查询多个MemTable

核心价值:通过内存缓冲将随机写入转换为顺序写入,是LSM树高写入性能的关键组件。

 

3、 刷盘(Flush)过程的技术细节

从MemTable到SSTable的刷盘过程看似简单,实际上涉及复杂的技术考量:

刷盘时机的精确控制:

刷盘时机的选择需要综合考虑多个因素:

  • 内存压力:MemTable占用内存过多时需要及时刷盘
  • WAL大小:WAL文件过大会影响恢复时间
  • 查询性能:过多的SSTable文件会影响读取性能
  • 系统负载:在低负载时进行刷盘可以减少对前台操作的影响

 

刷盘过程的原子性保证:

刷盘过程必须保证原子性:要么完全成功,要么完全失败。这通常通过以下步骤实现:

  1. 先写入临时文件
  2. 写入完成后原子性地重命名文件
  3. 更新元数据
  4. 删除对应的WAL段

如果任何步骤失败,都可以安全地重试或回滚。

 

压缩和编码的应用:

SSTable文件通常会应用压缩算法来减少存储空间。常用的压缩算法包括Snappy、LZ4、ZSTD等。压缩算法的选择需要在压缩率和CPU开销之间平衡。

除了通用压缩算法,还可以应用专门的编码技术,如Delta编码(存储键之间的差值而不是完整键)、前缀压缩(对具有相同前缀的键进行压缩)等。

 

三、Compaction策略:LSM树性能优化的核心机制

1、为什么LSM树必须要Compaction?LSM树设计带来的必然问题

LSM树通过"先写内存、再刷磁盘"的设计实现了出色的写入性能,但这种设计方式不可避免地引发了一系列问题。随着系统持续运行,磁盘上会不断积累大量小而分散的SSTable文件,这些文件的存在直接威胁到系统的长期性能。

  1. 读取性能的逐步恶化是最直观的问题。每次MemTable刷盘都会在磁盘上产生一个新的SSTable文件,而查询操作需要在这些不断增加的文件中逐一搜索目标数据。想象一下,如果系统运行一年后磁盘上有上千个SSTable文件,那么每次查询都可能变成一场"大海捞针"的过程。

  2. 存储空间的持续膨胀则是另一个严重问题。在LSM树中,删除操作并不会立即清除数据,而是简单地写入一个删除标记(Tombstone)。同时,对同一个key的多次更新会在不同的文件中产生多个版本。如果没有适当的清理机制,这些"垃圾数据"会让磁盘空间不断膨胀,最终可能消耗数倍于实际有效数据的存储空间。

  3. 系统缓存效率的下降也随之而来。当数据分散在大量小文件中时,操作系统的页缓存很难发挥作用,因为热数据和冷数据混杂在一起,缓存命中率会显著降低。

 

2、Compaction理论

2.1、Compaction概念

Compaction就是LSM树的"数据整理员",它的工作是定期将磁盘上散乱的小文件合并成更大、更有序的文件

(这里就涉及到了写放大,比如100M的数据触发了Compaction,此时有500M的文件需要合并,这就是5倍写放大:由100M的数据触发了500M的Compaction)

基本工作流程:

  1. 选择多个需要合并的SSTable文件
  2. 读取这些文件中的所有数据
  3. 进行排序合并,清理重复数据和删除标记
  4. 写出新的合并文件,删除旧文件

 

2.2、写放大的产生机制

写放大的本质:数据被重复写入磁盘。

举个具体例子:

用户写入100MB新数据(产生新的SSTable文件)。触发Compaction时,系统发现需要与4个旧文件(共400MB)合并,所以在Compaction过程中会:读取500MB数据 → 排序合并 → 写入500MB新文件。这里就涉及到了写放大: 写放大 = 实际写入(500MB) / 用户写入(100MB) = 5倍

为什么必须重写旧数据? 因为SSTable文件是不可变的,要实现全局有序和数据清理,只能通过重新生成文件来完成。就像重新整理书架,必须把所有书都重新摆放一遍。

 

2.3、分层架构的设计智慧

Leveled Compaction将数据组织成金字塔结构:

  • Level 0:10个文件(直接来自MemTable,允许重叠)
  • Level 1:100MB(文件间不重叠)
  • Level 2:1GB(每层容量10倍增长)
  • Level 3:10GB
  • 依此类推…

分层架构决定了当数据达到每层的限制后,会触发Compaction操作,控制了写放大(被整理的数据不会也来越大),也保证了数据的定期整理。如下是具体分析:

  1. 分层的核心价值:控制写放大。 由于每层容量呈指数增长,任何一条数据在整个生命周期中最多只会被重写log(N)次。比如100GB的数据库,单条数据最多重写4-5次,而不是无限次。

  2. Layer 0的特殊性: Level 0允许文件重叠是因为它们直接来自MemTable刷盘,反映的是写入时间顺序。从Level 1开始,所有层级都严格保持文件间无重叠,这样查询时每层最多只需检查一个文件。

  3. 分层合并策略: 当某层容量超限时,选择其中一个文件与下一层合并。这种"逐级下沉"的方式既保证了数据的定期整理,又将Compaction的开销分散到时间轴上,避免了突发的性能冲击。

  4. 核心权衡: Compaction通过增加写入成本(写放大)来换取读取性能和存储效率的提升。分层架构则巧妙地将这种成本控制在可预测的范围内,这正是LSM树设计的精髓所在。

 

3、Size-Tiered与Leveled:两种哲学的对比

3.1 Size-Tiered的简洁哲学

与Leveled Compaction的复杂精巧相比,Size-Tiered Compaction体现了另一种设计哲学:简洁而直接。它的策略很简单——将大小相似的文件合并在一起,形成更大的文件,如此反复,最终形成金字塔式的大小分布。

这种策略的最大优势是写入友好。由于每个数据项被重写的次数相对较少,系统可以维持很高的写入吞吐量。对于那些以写入为主、读取相对较少的应用场景,Size-Tiered策略往往是更好的选择。

3.2 策略选择的智慧

然而,Size-Tiered策略也有其代价:读取性能相对较差,因为查询时可能需要检查多个大文件;空间回收效率也不如Leveled策略,删除的数据需要更长时间才能被清理。

这就引出了一个重要的工程问题:如何根据具体的应用场景选择合适的策略?

对于日志收集、监控指标等写密集型场景,Size-Tiered策略的高写入性能和低写放大特性使其成为理想选择。而对于用户数据、交易记录等需要频繁查询的场景,Leveled策略的优秀读取性能和空间效率则更有优势。

 

4、Compaction的本质与价值

从更深层的角度来看,Compaction策略的选择实际上反映了系统设计中一个永恒的主题:如何在相互冲突的需求之间找到最佳平衡点

LSM树通过Compaction机制,将写入时的简单快速和读取时的复杂优化分离开来,这种"延迟优化"的思想在很多系统设计中都有体现。它告诉我们,并不是所有的性能优化都需要在第一时间完成,有时候将复杂性延后处理反而能获得更好的整体效果。

无论选择哪种Compaction策略,核心都在于深入理解应用的特点和需求。没有完美的策略,只有最适合的选择。这正是LSM树设计哲学的精髓所在:通过灵活的策略配置,让同一套基础架构适应不同的应用场景,这种适应性正是现代分布式系统成功的关键因素之一。

 

四、 LSM树读取路径:从简单写入到复杂查询

1. 为什么LSM树的读取比写入复杂?

写入很简单: 数据只需要写入一个地方——当前的MemTable,速度极快。

读取很复杂: 由于LSM树的设计特点,一个key的最新数据可能存在于多个地方,查询时必须按优先级搜索所有可能的位置:

  1. MemTable(最新数据)
  2. Immutable MemTable(准备刷盘的数据)
  3. Level 0 SSTable文件(最近刷盘的数据)
  4. Level 1, 2, 3…文件(较老的数据)

核心问题: 查询一个key,最坏情况下可能需要检查几十个甚至上百个文件!这就是所谓的"读放大"问题。

为什么不能像B+树那样直接定位? 因为LSM树为了优化写入性能,将数据分散存储在多个时间层次中,牺牲了读取的直接性。

 

2. Bloom Filter:LSM树读取优化的核心武器

问题的严重性: 如果每次查询都要打开几十个文件进行搜索,性能会极其糟糕。

Bloom Filter的解决思路: 在不实际打开文件的情况下,快速判断"这个key绝对不在这个文件中"。

工作原理简单说明:

  • 每个SSTable文件都配备一个Bloom Filter(一个小的内存数据结构)
  • 查询时先问Bloom Filter:“key X可能在这个文件里吗?”
  • 如果答案是"绝对不在",直接跳过这个文件;如果答案是"可能在",才实际打开文件搜索

效果: 通过Bloom Filter,大部分文件可以被快速排除,实际需要打开的文件数量从几十个降低到几个。

关键参数权衡: Bloom Filter的假阳性率越低(误判率越低),需要的内存越多。典型配置是1%的假阳性率,这意味着100次查询中可能有1次会误判需要打开不必要的文件,但这个代价是可以接受的。

核心价值: Bloom Filter将LSM树的读取复杂度从"必须搜索N个文件"优化为"大概率只需搜索1-2个文件",这是LSM树能够在读写混合负载下保持合理性能的关键技术。

 

五、LSM树性能特性:三个核心权衡

1、写放大、读放大、空间放大的本质

LSM树的性能特性可以归结为三个核心权衡,这些权衡决定了LSM树适用的场景和优化方向。

写放大:为了长期性能牺牲短期成本

写放大的本质是"数据被重复写入"。想象一下整理房间:你不能只把新物品放进去,还要定期重新整理所有物品来保持房间的有序性。LSM树也是如此——Compaction过程会重新写入已存在的数据来维持整体结构。

典型的Leveled Compaction写放大在10-30倍之间。这看起来很高,但关键在于它是摊销的:不是每次写入都有30倍开销,而是在长期运行中平均每字节数据会被写入10-30次。单次写入依然很快,只是后台会有持续的整理成本。

 

读放大:分散存储带来的查询复杂性

读放大源于LSM树的核心设计:数据分散在多个文件中。最坏情况下,一次查询可能需要检查1个MemTable + 1个Immutable MemTable + 10个Level 0文件 + 每层1个文件。如果有6层,就是18个数据源。

Bloom Filter是解决这个问题的关键武器。它就像图书馆的索引卡片,告诉你"这本书绝对不在这个书架上",让你避免无谓的搜索。通过Bloom Filter,实际需要搜索的文件数量从十几个降低到1-2个。

 
空间放大:延迟清理的代价

空间放大主要来自两个原因:删除标记(Tombstone)和版本重叠。删除操作不会立即释放空间,而是写入删除标记;同一个key的多个版本可能同时存在于不同文件中。只有通过Compaction才能真正清理这些"垃圾数据"。

典型的空间放大在1.1-2倍之间,这意味着存储1GB有效数据可能需要1.1-2GB的磁盘空间。

 

2、不同存储介质的性能影响

机械硬盘:LSM树的天然优势

LSM树在机械硬盘上表现出色,因为它将随机I/O转换为顺序I/O。机械硬盘的随机I/O性能只有100-200 IOPS,但顺序I/O可以达到100MB/s以上。LSM树的顺序写入特性完美契合了机械硬盘的性能特点。

在机械硬盘上,读取性能本身就受限于寻道时间,所以可以采用更激进的Size-Tiered Compaction策略,用更高的读放大换取更低的写放大,因为读取瓶颈主要在磁盘寻道而不是文件数量。

 

SSD:新的挑战与机遇

SSD改变了LSM树的性能平衡。SSD的随机I/O性能大幅提升,但引入了新的考虑因素:写入寿命限制。SSD的每个存储单元只能承受有限次数的写入,LSM树的写放大会加速SSD的磨损。

但SSD也带来了新的优化机会:高度并行的I/O能力。现代SSD可以同时处理多个I/O请求,LSM树可以通过并发Compaction、并行读取等方式充分利用这种并行性,获得比机械硬盘更好的整体性能。

核心启示:LSM树的性能特性不是固定的,而是与底层存储介质密切相关。理解这些权衡关系是优化LSM树性能的关键。在机械硬盘上优化写入,在SSD上平衡写入寿命与性能,在NVMe上充分利用超高IOPS——不同的存储介质需要不同的优化策略。

 

六、LSM树的工程实践:监控与恢复的核心机制

1、为什么LSM树需要特殊的监控策略?

传统数据库的监控相对简单,因为数据结构稳定,性能瓶颈容易定位。但LSM树的性能是动态变化的——Compaction的进行会影响读写性能,缓存的命中率会随数据分布变化,这种动态性要求更精密的监控策略。

最关键的三个监控指标:

写放大系数 是LSM树健康状况的核心指标。正常情况下应该在10-30倍之间,如果突然飙升到50倍以上,通常意味着Compaction跟不上写入速度,系统正在"积压工作"。这就像工厂的生产线——如果装配速度跟不上零件供应,库存就会堆积。

Compaction队列长度 反映了系统的"消化能力"。队列长度持续增长表明后台整理工作已经超负荷,这会逐步影响读取性能。正常情况下队列应该保持在较低水平,偶尔的峰值是正常的,但持续的高队列长度需要调整Compaction策略。

缓存命中率 直接决定了读取性能。LSM树对缓存的依赖比B+树更强,因为数据分散在多个文件中。如果缓存命中率从95%下降到85%,读取延迟可能增加数倍。这就像图书馆的常用书架——如果经常找的书不在手边,每次都要跑到仓库去取。

 

性能问题的简单诊断逻辑:

  • 写入变慢?检查Compaction队列是否积压
  • 读取变慢?检查缓存命中率和文件数量
  • 空间暴增?检查删除数据的清理频率

 

2、WAL:LSM树可靠性的保险机制

LSM树的数据首先写入内存(MemTable),在刷盘之前数据是易失的。WAL(Write-Ahead Log)就是这种设计的"保险丝"——确保即使系统崩溃,也能恢复所有已确认的写入操作。

WAL的工作原理很简单: 每次写入数据前,先将操作记录写入磁盘上的日志文件。这个日志记录包含了重建数据所需的所有信息:key、value、操作类型、时间戳等。由于WAL是顺序写入,速度很快,不会成为性能瓶颈。

崩溃恢复的过程: 系统重启时,会读取WAL文件,按顺序重放所有操作,重建内存中的MemTable状态。这个过程就像重放录像带——按照时间顺序重新执行所有操作,最终达到崩溃前的状态。

WAL的生命周期管理: WAL文件不能无限增长,当对应的MemTable成功刷盘后,相关的WAL段就可以删除了。这需要精确的元数据管理来跟踪哪些WAL段还有用,哪些可以安全删除。

为什么WAL机制对LSM树特别重要? 因为LSM树的设计将写入操作分成了两个阶段:快速写入内存和延迟写入磁盘。WAL填补了这两个阶段之间的可靠性空隙,确保"写入成功"的承诺能够兑现。

核心价值: 通过精确的监控和可靠的恢复机制,LSM树在保持高性能的同时确保了数据的安全性。这种监控-恢复体系是LSM树在生产环境中稳定运行的基础保障。

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

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

相关文章

Pygame 大鱼吃小鱼

【Pygame 大鱼吃小鱼】是一款基于Python编程语言和Pygame库开发的趣味游戏。Pygame是Python中一个广泛用于开发2D游戏的开源模块集合,它提供了丰富的功能,如窗口管理器、事件处理、图形绘制等,使得初学者也能快速上手创建游戏。 这段 Python …

【为什么在触发的事件中修改控件属性需要使用`Invoke`】

在C#中,特别是在使用Windows Forms或WPF等GUI框架时,控件的属性和状态通常只能在创建它们的线程(即UI线程,即主线程或用户界面线程)中直接修改。这是由于这些框架的设计基于单线程模型,其中所有与用户界面&…

Android 当apk是系统应用时,无法使用webView的解决方案

最近在做项目时,遇到了一个无法使用webView的问题,apk是系统应用,点击加载webView时应用就是崩溃,原因是系统应用时,Android会觉得webView不安全,不避让加载。 解决的思路就是使用映射,把原生的…

ArcGIS Pro无插件加载(无偏移)天地图!一次添加长久使用

以前我们介绍过:ArcGIS无插件加载(无偏移)天地图。这次我们来介绍ArcGIS Pro中如何添加天地图。 我们将通过从天地图官网自己添加服务链接并添加至收藏的方式以及应急的方法来做本次的介绍。天地图的数据主要包括影像、电子地图、地形图等。我…

Go堆内存管理

# Go堆内存管理 1. Go内存模型层级结构 Golang内存管理模型与TCMalloc的设计极其相似。基本轮廓和概念也几乎相同,只是一些规则和流程存在差异。 2. Go内存管理的基本概念 Go内存管理的许多概念在TCMalloc中已经有了,含义是相同的,只是名字…

零售 EDI:Chewy EDI 项目注意事项

在此前的文章《供应商对接Chewy的EDI需求》中,介绍了Chewy的EDI需求,本文主要为大家分享Chewy对于各个业务单据的细节性需求,了解这些细节性注意事项将帮助企业快速基于知行软件提供的EDI服务与Chewy建立EDI对接。 基于知行之桥EDI系统能够通…

Android录制视频自带铺满多行水印

文章目录 引言环境要求代码实现总结 引言 之前做过几种水印需求,这篇文章是关于使用Android原生库开发录制视频自带满帧文字水印。 环境要求 Android 7.0以上Android Studio ,官方开发者官网视频录制功能参考开源库PictureSelector的camerax库 //用到的…

观远ChatBI:加速零售消费企业数据驱动的敏捷决策

近年来,随着国产大模型(如DeepSeek)的快速发展,企业对智能化数据分析工具的需求日益增长。观远数据推出的ChatBI,基于大语言模型(LLM)打造,旨在通过自然语言交互降低数据分析门槛&am…

鸿蒙NEXT-鸿蒙三层架构搭建,嵌入HMRouter,实现便捷跳转,新手攻略。(1/3)

接下来,我将手把手带领大家去完善,搭建一个鸿蒙的三层架构,另实现HMRouter的嵌入。完成后,大家可任意跳转页面,在三层架构中,书写属于自己的篇章。 第0步,项目与AGC华为控制台关联起来 首先AG…

鸿蒙ArkTs仿网易云音乐项目:架构剖析与功能展示

鸿蒙ArkTs仿网易云音乐项目:架构剖析与功能展示 一、引言 在移动应用开发的浪潮中,音乐类应用始终占据着重要的一席之地。网易云音乐凭借其丰富的音乐资源、个性化的推荐算法和独特的社交互动功能,深受广大用户的喜爱。本文将详细介绍一个基…

【web 安全】从 HTTP 无状态到现代身份验证机制

文章目录 Web 安全与系统设计Web存在的问题:Web 是无状态的解决方案一、早期解决方案:Session Cookie 的诞生二、第二阶段:Token 的出现(前后端分离 移动端的解决方案)三、分析总结:1.早期版本&#xff1…

FlutterUnit TolyUI | 布局游乐场

FlutterUnit 基于 TolyUI 大大简化了界面构建的代码复杂程度,因此之前想要实现的一些小功能,就可以轻松支持。布局游乐场是通过交互的方式来 直观体验 组件的布局特性,从而更易学和掌握。目前 FlutterUnit 已在 知识集录模块新增了 布局宝库&…

【数据分析一:Data Collection】信息检索

本节内容含有各典型数据集的推荐,以及其网址,大家根据需要自取 一、检索 最简单、最灵活的数据获取方式就是依靠检索: Google:更适合搜索英文信息 Google Dataset Search(Google 数据集搜索) 网址&…

23.ssr和csr的对比?如何依赖node.js实现

1.为什么说ssr 的node中间层请求速度快。相当于内网? 那vue.js加载怎么没有ssr和csr的说法啊 第一问:为什么说 SSR 的 Node 中间层请求速度快?是不是相当于内网? ✅ 是的,本质上就是「内网请求」,所以更快…

力扣刷题(第六十四天)

灵感来源 - 保持更新,努力学习 - python脚本学习 第一个错误的版本 解题思路 初始化左右边界:左边界 left 1,右边界 right n。二分查找循环: 计算中间版本号 mid。若 mid 是错误版本,说明第一个错误版本在 [le…

【图像处理入门】11. 深度学习初探:从CNN到GAN的视觉智能之旅

摘要 深度学习为图像处理注入了革命性动力。本文将系统讲解卷积神经网络(CNN)的核心原理,通过PyTorch实现图像分类实战;深入解析迁移学习的高效应用策略,利用预训练模型提升自定义任务性能;最后揭开生成对抗网络(GAN)的神秘面纱,展示图像生成与增强的前沿技术。结合代…

C++法则4: 如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。

C法则4: 如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。 拷贝构造函数的定义: 第一个参数是自身类类型的引用: 必须是引用(通常为const引用&…

从头搭建环境安装k8s遇到的问题

基本信息 master节点IP: 172.31.0.3 node01节点IP:172.31.0.4 node02节点IP:172.31.0.5 子网掩码:255.255.0.0 网关:172.31.0.2 DNS:114.114.114.114 安装前要检查的信息 检查三台主机的mac地址是否重复&#xff1a…

Flask入门指南:从零构建Python微服务

1. Flask 是什么? Flask 是一个 微框架(Microframework),特点包括: 轻量灵活:核心仅包含路由和模板引擎,其他功能通过扩展实现易于学习:代码直观,适合快速开发小型应用…

【LINUX网络】网络socet接口的基本使用以及实现简易UDP通信

根据本系列上两篇关于网络的初识介绍,现在我们开始实现一个UDP接口,以加强对该接口的理解。 1 . 服务器端 在本篇中,主要按照下面内容来实现: 创建并封装服务端:了解创建服务端的基本步骤 创建并封装客户端&#xff0…