数据湖之Hudi基础:核心原理

news2024/10/6 2:26:46

继续Hudi核心概念

参考官网描述与尚硅谷hudi公开资料

文章目录

  • 基本概念
    • 时间轴TimeLine
      • 1.Instants action 在表上执行的操作类型
      • 2.Instant time
      • 3.State
      • 两个时间概念
    • 文件布局(FileLayout)
    • 索引 Index
    • 表类型(Table Types)
      • Copy On Write
      • Merge On Read
      • MOR和COW对比
    • 查询类型
  • 数据写
    • 写操作
    • 写流程(UPSERT)
      • COW
      • MOR
    • 写流程(INSERT)
      • COW
      • MOR
    • 写流程(INSERT OVERWRITE)
      • COW
      • MOR
      • 优点
      • 缺点
    • Key 生成策略
    • 删除策略
    • Hudi写小结
  • 数据读
    • Snapshot读
    • Incremental读
    • Streaming读
    • Compaction

本文重点参考自官方文档(v0.12.1),英文好的建议直接看官方文档:https://hudi.apache.org/docs/0.12.1/concepts/

基本概念

时间轴TimeLine

在这里插入图片描述

Hudi的核心是维护表上在不同的即时时间(instants)执行的所有操作的时间轴(timeline)

一个instant由以下三个部分组成:

1.Instants action 在表上执行的操作类型

Instants action的值取类型如下

  • COMMITS:一次Commit表示将一批数据原子性的写入一个表
  • CLEANS:清除表不再需要的旧版本文件的后台活动
  • DELTA_COMMIT:增量提交指的是将一批数据原子性地写入一个MergeOnRead类型地表,其中部分或所有数据可以写入增量日志。
  • COMPACTION:合并Hudi内部差异数据结构地后台活动,例如:将更新操作从基于行地log日志文件合并到列式存储地数据文件。在内部,COMPACTION体现为timeline上地特殊提交
  • ROLLBACK:表示当commit、delta_commit不成功时进行回滚,其会删除在写入过程中产生地部分文件
  • SAVEPOINT:将某些文件组标记为已保存,以便其不会被删除。发生问题时可以根据SAVEPOINT将数据集还原到时间轴上地某个点。

2.Instant time

一般是一个时间戳,比如:20230117121314098,按照动作开始时间的顺序单调增加

3.State

状态

  • REQUESTED:表示某个action已经调度但是尚未执行
  • INFLIGHT:表示action当前正在执行
  • COMPLETED:表示timeline上的action已经完成

两个时间概念

hudi的两个重要时间概念

  • Arrival time:数据到达Hudi的时间的commit time(类比flink的摄入时间)
  • Event time:数据自己的时间

那么当一条延迟的数据到来,是否可以被消费到呢?他会落盘到哪个分区?

在这里插入图片描述

上图中采用时间(小时)作为分区字段,从 10:00 开始陆续产生各种 commits,10:20 来了一条 9:00 的数据,根据event time该数据仍然可以落到 9:00 对应的分区,通过 timeline 直接消费 10:00 (commit time)之后的增量更新(只消费有新 commits 的 group),那么这条延迟的数据仍然可以被消费到。

文件布局(FileLayout)

Hudi的一个表文件结构如何?

在这里插入图片描述

Hudi存储分为两部分:

  • 元数据:hoodie目录对应着表的元数据信息,包括表的版本管理(Timeline)、归档目录(存放过时的instant),一个instant记录了一次提交的行为、时间戳和状态(action、time、state),Hudi以时间轴的形式维护了在数据集上执行的所有操作的元数据
  • 数据:和Hive一样,以分区方式存放数据;分区里有BaseFile(.parquet)和LogFile(.log.*)

在这里插入图片描述

文件管理如下

  • 数据表组织成分布式文件系统基本路径(basepath)下的目录结构

  • 表被划分为多个分区,这些分区时包含该分区数据的文件夹,非常类似Hive表

  • 在每个分区中,文件被组织成文件组,由文件ID唯一标识

  • 每个文件组包含几个文件分片 FileSlice

  • 每个文件分片包含:

    • 一个基本文件(.parquet):在某个commit、compaction即时时间(instant time)生成的(Merge On Read可能没有)
    • 多个日志文件(.log.*):这些日志文件包含自生成基本文件以来对基本文件的插入、更新(COW没有)
  • 多版本并发控制文件(Multiversion Concurrency Control,MVCC)

    • compaction操作:合并日志和基本文件以及产生新的文件片
    • clean操作:清除不适用的旧的文件片以回收文件系统上的空间

    在这里插入图片描述

  • basefile(parquet文件)在footer的meta去记录了record key组成的BloomFilter,用于在file based index的视线中实现高效率的key contants检测。只有不在BloomFilter的key才需要扫描整个文件排除BloomFilter的假阳

  • Hudi 的 log (avro 文件)是自己编码的,通过积攒数据 buffer 以 LogBlock 为单位写出,每个 LogBlock 包含 magic number、size、content、footer 等信息,用于数据读、校验和过滤。

    在这里插入图片描述

索引 Index

  • 1)原理

    Hudi通过索引机制提供高效的upserts,具体是将给定的hoodie key(record key + partition path)与文件id(文件组)建立唯一映射。这种映射关系,数据第一次写入文件后保持不变,所以,一个 FileGroup 包含了一批 record 的所有版本记录。Index 用于区分消息是 INSERT 还是 UPDATE。

在这里插入图片描述

​ 为了避免不必要的读写,引入索引。那么,在更新数据时可以快速被定位到对应FileGroup。上图,白色为基本文件,黄色是更新数据。有了索引机制,可以做到:避免读取不需要的文件、避免更新不必要的文件、无需将更新数据与历史数据做分布式关联,只需要在 File Group 内做合并。

  • 2)索引选项
Index类型原理优点缺点
Bloom Index默认配置,使用布隆过滤器来判断记录存在与否,也可选使用record key的范围裁剪需要的文件效率高,不依赖外部系统,数据和索引保持一致性因假阳性问题,还需回溯原文件再查找一遍
Simple Index把update/delete操作的新数据和老数据进行join实现最简单,无需额外的资源性能比较差
HBase Index把index存放在HBase里面。在插入 File Group定位阶段所有task向HBase发送 Batch Get 请求,获取 Record Key 的 Mapping 信息对于小批次的keys,查询效率高需要外部的系统,增加了运维压力
Flink State-based IndexHUDI 在 0.8.0 版本中实现的 Flink witer,采用了 Flink 的 state 作为底层的 index 存储,每个 records 在写入之前都会先计算目标 bucket ID。不同于 BloomFilter Index,避免了每次重复的文件 index 查找

注意:Flink只有一种state based index(和bucket_index),其他index是Spark可选配置。

  • 3)全局索引和非全局索引

    • 全局索引:全表范围要求键唯一,保证有且只有一个对应记录。但是表增大后,update/delete操作损失性能越高,因此适用于小表

    • 非全局索引:默认索引。保证数据在分区内唯一。依靠写入器为同一个记录的update/delete提供一致的分区路径,同时大幅提高了效率,更适用于大表。

​ 从index的维护成本和写入性能的角度考虑,维护一个global index的难度更大,对写入性能的影响也更大,所以需要non-global index。

当使用HBase 作索引时,相当于一个全局索引

当使用bloom和simple index时,分别有全局选项

hoodie.index.type=GLOBAL_BLOOM

hoodie.index.type=GLOBAL_SIMPLE

  • 4)索引选择策略

    • 对事实表的延迟更新

      ​ 许多公司会在NoSQL数据存储中存放大量的交易数据。例如共享出行的行程表、股票买卖记录的表、和电商的订单表。这些表通常一直在增长,且大部分的更新随机发生在较新的记录上,而对旧记录有着长尾分布型的更新。这通常是源于交易关闭或者数据更正的延迟性。换句话说,大部分更新会发生在最新的几个分区上而小部分会在旧的分区。

    在这里插入图片描述

    ​ 对于这样的作业模式,布隆索引就能表现地很好,因为查询索引可以靠设置得当的布隆过滤器来裁剪很多数据文件。另外,如果生成的键可以以某种顺序排列,参与比较的文件数会进一步通过范围裁剪而减少。Hudi用所有文件的键域来构造区间树,这样能来高效地依据输入的更删记录的键域来排除不匹配的文件。

    ​ 为了高效地把记录键和布隆过滤器进行比对,即尽量减少过滤器的读取和均衡执行器间的工作量,Hudi缓存了输入记录并使用了自定义分区器和统计规律来解决数据的偏斜。有时,如果布隆过滤器的假阳性率过高,查询会增加数据的打乱操作。Hudi支持动态布隆过滤器(设置hoodie.bloom.index.filter.type=DYNAMIC_V0)。它可以根据文件里存放的记录数量来调整大小从而达到设定的假阳性率

    • 对事件表的去重

      ​ 事件流无处不在,事件数通常是事实表大小的10-100倍

      ​ 事件通常把时间(到达时间、处理时间)作为首类处理对象,比如物联网的事件流、点击流数据、广告曝光数等等。由于这些大部分都是仅追加的数据,插入和更新只存在于最新的几个分区中。由于重复事件可能发生在整个数据管道的任一节点,在存放到数据湖前去重是一个常见的需求。

      在这里插入图片描述

      ​ 去重时,虽然可以用索引,但索引存储的消耗也会随着事件增长而线性增长,以至于变得不可行。

      ​ 事实上,有范围裁剪功能的布隆索引是最佳的解决方案。我们可以利用作为首类处理对象的时间来构造由事件时间戳和事件id(event_ts+event_id)组成的键,这样插入的记录就有了单调增长的键。这会在最新的几个分区里大幅提高裁剪文件的效益。

    • 对维度表的随机更新删除

      在这里插入图片描述

      ​ 如果范围比较不能裁剪更多文件,那bloom索引并不能带来较好效益。在这种随机写入的场景,更新操作,通常会触及表里大多数文件从而导致bloom功能退化(对所有文件都可能标阳,导致所有文件都要scan),此时使用简单索引更合适,因为它不用提前剪裁,而是直接和所有文件的所需字段连接,如果有能力,也可以使用HBase索引,它对随机场景会有更好的查询效率

      ​ 当使用全局索引时,也可以考虑通过设置hoodie.bloom.index.update.partition.path=truehoodie.simple.index.update.partition.path=true来处理 的情况;例如对于以所在城市分区的用户表,会有用户迁至另一座城市的情况。这些表也非常适合采用Merge-On-Read表型。

表类型(Table Types)

Copy On Write

简称COW表,只有数据文件/基本文件(.parquet),没有增量日志文件(.log.*)

对每一个新批次写入都将创建相应数据文件的新版本(新的FileSlice),新版本文件包括旧版本文件的记录以及来自传入批次的记录(全量最新)。

在这里插入图片描述

​ 假设我们有 3 个文件组(如上图)。我们进行一批新的写入,在索引后,我们发现这些记录与File group 1 和File group 2 匹配,然后有新的插入,我们将为其创建一个新的文件组(File group 4)。

​ 因此data_file1 和 data_file2 都将创建更新的版本,data_file1 V2 是data_file1 V1 的内容与data_file1 中传入批次匹配记录的记录合并。

​ 由于在写入期间进行合并,COW 会产生一些写入延迟。但是COW 的优势在于它的简单性,不需要其他表服务(如压缩),也相对容易调试。

Merge On Read

简称MOR表。包含列存的基本文件(.parquet)和行存的增量日志文件(基于行的avro格式,.log.*)。

​ 顾名思义,MOR表的合并成本在读取端。因此在写入期间我们不会合并或创建较新的数据文件版本。标记/索引完成后,对于具有要更新记录的现有数据文件,Hudi 创建增量日志文件并适当命名它们,以便它们都属于一个文件组。

在这里插入图片描述

​ 读取端将实时合并基本文件及其各自的增量日志文件。每次的读取延迟都比较高(因为查询时进行合并),所以 Hudi 使用压缩机制来将数据文件和日志文件合并在一起并创建更新版本的数据文件。

在这里插入图片描述

​ 用户可以选择内联或异步模式运行压缩。Hudi也提供了不同的压缩策略供用户选择,最常用的一种是基于提交的数量。例如可以将压缩的最大增量日志配置为 4。这意味着在进行 4 次增量写入后,将对数据文件进行压缩并创建更新版本的数据文件。压缩完成后,读取端只需要读取最新的数据文件,而不必关心旧版本文件。

MOR表的写入行为,依据 index 的不同会有细微的差别:

  • 对于 BloomFilter 这种无法对 log file 生成 index 的索引方案,对于 INSERT 消息仍然会写 base file (parquet format),只有 UPDATE 消息会 append log 文件(因为 base file 已经记录了该 UPDATE 消息的 FileGroup ID)。

  • 对于可以对 log file 生成 index 的索引方案,例如 Flink writer 中基于 state 的索引,每次写入都是 log format,并且会不断追加和 roll over。

MOR和COW对比

CopyOnWriteMergeOnRead
数据延迟
查询延迟
Update(I/O) 更新成本高(重写整个Parquet文件)低(追加到增量日志)
Parquet文件大小低(更新成本I/O高)较大(低更新成本)
写放大低(取决于压缩策略)

查询类型

hudi支持如下三种查询类型

  • Snapshot Queries

    快照查询,可查指定commit/delta commit即时操作后表的最新快照。

    ​ 在读时合并(MOR)表的情况下,它通过即时合并最新文件片的基本文件和增量文件来提供近实时表(几分钟)。

    ​ 对于写时复制(COW),它可以替代现有的parquet表(或相同基本文件类型的表),同时提供upsert/delete和其他写入方面的功能,可以理解为查询最新版本的Parquet数据文件。

    下图是COW的快照查询:

    在这里插入图片描述

  • Incremental Queres

    增量查询,可以查询给定commit/delta commit即时操作以来新写入的数据。有效的提供变更流来启用增量数据管道。

  • Read Optimized Queries

    读优化查询,可查看给定的commit/compact即时操作的表的最新快照。仅将最新文件片的基本/列文件暴露给查询,并保证与非Hudi表相同的列查询性能。

    下图是MOR表的快照查询与读优化查询的对比:

在这里插入图片描述

Read Optimized Queries是对Merge On Read表类型快照查询的优化。

SnapshotRead Optimized
数据延迟
查询延迟高(合并列式基础文件+行式增量日志文件)低(原始列式基础文件)
  • 不同表支持的查询类型

    Table Type支持的查询类型
    COWSnapshot queries+ Incremental queries
    MORSnapshot queries+ Incremental queries + Read Optimized Queries

在这里插入图片描述

数据写

写操作

  • UPSERT:默认行为,数据先通过 index 打标(INSERT/UPDATE),有一些启发式算法决定消息的组织以优化文件的大小( CDC 导入)
  • INSERT:跳过 index,写入效率更高 (Log Deduplication)
  • BULK_INSERT:写排序,对大数据量的 Hudi 表初始化友好,对文件大小的限制 best effort(写 HFile)

写流程(UPSERT)

COW

  • (1)先对 records 按照 record key 去重

  • (2)首先对这批数据创建索引 (HoodieKey => HoodieRecordLocation);通过索引区分哪些 records 是 update,哪些 records 是 insert(key 第一次写入)

  • (3)对于 update 消息,会直接找到对应 key 所在的最新 FileSlice 的 base 文件,并做 merge 后写新的 base file (新的 FileSlice)

  • (4)对于 insert 消息,会扫描当前 partition 的所有 SmallFile(小于一定大小的 base file),然后 merge 写新的 FileSlice;如果没有 SmallFile,直接写新的 FileGroup + FileSlice

MOR

  • (1)先对 records 按照 record key 去重(可选)

  • (2)首先对这批数据创建索引 (HoodieKey => HoodieRecordLocation);通过索引区分哪些 records 是 update,哪些 records 是 insert(key 第一次写入)

  • (3)如果是 insert 消息,如果 log file 不可建索引(默认),会尝试 merge 分区内最小的 base file (不包含 log file 的 FileSlice),生成新的 FileSlice;如果没有 base file 就新写一个 FileGroup + FileSlice + base file;如果 log file 可建索引,尝试 append 小的 log file,如果没有就新写一个 FileGroup + FileSlice + base file

  • (4)如果是 update 消息,写对应的 file group + file slice,直接 append 最新的 log file(如果碰巧是当前最小的小文件,会 merge base file,生成新的 file slice)

  • (5)log file 大小达到阈值会 roll over 一个新的

写流程(INSERT)

COW

  • (1)先对 records 按照 record key 去重(可选)

  • (2)不会创建 Index

  • (3)如果有小的 base file 文件,merge base file,生成新的 FileSlice + base file,否则直接写新的 FileSlice + base file

MOR

  • (1)先对 records 按照 record key 去重(可选)

  • (2)不会创建 Index

  • (3)如果 log file 可索引,并且有小的 FileSlice,尝试追加或写最新的 log file;如果 log file 不可索引,写一个新的 FileSlice + base file

写流程(INSERT OVERWRITE)

在同一分区中创建新的文件组集。现有文件组被标记为 “删除”。根据新记录的数量创建新的文件组

COW

在插入分区之前插入相同数量的记录覆盖插入覆盖更多的记录插入重写1条记录
分区包含file1-t0.parquet,file2-t0.parquet。分区将添加file3-t1.parquet,file4-t1.parquet。file1, file2在t1后的元数据中被标记为无效。分区将添加file3-t1.parquet,file4-t1.parquet,file5-t1.parquet,…,fileN-t1.parquet。file1, file2在t1后的元数据中被标记为无效分区将添加file3-t1.parquet。file1, file2在t1后的元数据中被标记为无效。

MOR

在插入分区之前插入相同数量的记录覆盖插入覆盖更多的记录插入重写1条记录
分区包含file1-t0.parquet,file2-t0.parquet。.file1-t00.logfile3-t1.parquet,file4-t1.parquet。file1, file2在t1后的元数据中被标记为无效。file3-t1.parquet, file4-t1.parquet…fileN-t1.parquetfile1, file2在t1后的元数据中被标记为无效分区将添加file3-t1.parquet。file1, file2在t1后的元数据中被标记为无效。

优点

  • (1)COW和MOR在执行方面非常相似。不干扰MOR的compaction。

  • (2)减少parquet文件大小。

  • (3)不需要更新关键路径中的外部索引。索引实现可以检查文件组是否无效(类似于在HBaseIndex中检查commit是否无效的方式)。

  • (4)可以扩展清理策略,在一定的时间窗口后删除旧文件组。

缺点

  • (1)需要转发以前提交的元数据。

    • 在t1,比如file1被标记为无效,我们在t1.commit中存储 “invalidFiles=file1”(或者在MOR中存储deltacommit)
    • 在t2,比如file2也被标记为无效。我们转发之前的文件,并在t2.commit中标记 “invalidFiles=file1, file2”(或MOR的deltacommit)
  • (2)忽略磁盘中存在的parquet文件也是Hudi的一个新行为, 可能容易出错,我们必须认识到新的行为,并更新文件系统的所有视图来忽略它们。这一点可能会在实现其他功能时造成问题。

Key 生成策略

用来生成 HoodieKey(record key + partition path),目前支持以下策略:

  • 支持多个字段组合 record keys

  • 支持多个字段组合的 parition path (可定制时间格式,Hive style path name)

  • 非分区表

删除策略

  • 1)逻辑删:将 value 字段全部标记为 null

  • 2)物理删:

    • (1)通过 OPERATION_OPT_KEY 删除所有的输入记录

    • (2)配置 PAYLOAD_CLASS_OPT_KEY = org.apache.hudi.EmptyHoodieRecordPayload 删除所有的输入记录

    • (3)在输入记录添加字段:_hoodie_is_deleted

Hudi写小结

通过对写流程的梳理可以了解到 Apache Hudi 相对于其他数据湖方案的核心优势:

  • (1)写入过程充分优化了文件存储的小文件问题,Copy On Write 写会一直将一个 bucket (FileGroup)的 base 文件写到设定的阈值大小才会划分新的 bucket;Merge On Read 写在同一个 bucket 中,log file 也是一直 append 直到大小超过设定的阈值 roll over。

  • (2)对 UPDATE 和 DELETE 的支持非常高效,一条 record 的整个生命周期操作都发生在同一个 bucket,不仅减少小文件数量,也提升了数据读取的效率(不必要的 join 和 merge)。

数据读

Snapshot读

​ 读取所有 partiiton 下每个 FileGroup 最新的 FileSlice 中的文件,Copy On Write 表读 parquet 文件,Merge On Read 表读 parquet + log 文件

Incremental读

​ Spark读:https://hudi.apache.org/docs/querying_data.html#spark-incr-query

​ 当前的 Spark data source 可以指定消费的起始和结束 commit 时间,读取 commit 增量的数据集。但是内部的实现不够高效:拉取每个 commit 的全部目标文件再按照系统字段 hoodie_commit_time apply 过滤条件。

Streaming读

0.8.0 版本后 HUDI Flink writer 支持实时的增量订阅,可用于同步 CDC 数据,日常的数据同步 ETL pipeline。Flink 的 streaming 读做到了真正的流式读取,source 定期监控新增的改动文件,将读取任务下派给读 task。

Compaction

  • (1)没有 base file:走 copy on write insert 流程,直接 merge 所有的 log file 并写 base file

  • (2)有 base file:走 copy on write upsert 流程,先读 log file 建 index,再读 base file,最后读 log file 写新的 base file

Flink 和 Spark streaming 的 writer 都可以 apply 异步的 compaction 策略,按照间隔 commits 数或者时间来触发 compaction 任务,在独立的 pipeline 中执行。

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

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

相关文章

echarts:实现3D地图版块叠加动效散点效果

需求描述 如下图所示,展示3D效果的地图版块,并叠加显示动效散点: 实现思路 首先是3D地图版块效果的实现,可以参考广州3D地图;而动效散点的实现,可以参考地图发散分布。 这里再提一个经过尝试并不行的思…

【mmdeploy】mmseg转ONNX/TensorRT,附推理代码

目录 1.关于mmdeploy 2.环境安装 2.1预编译安装(Linux-x86_64, CUDA 11.x, TensorRT 8.2.3.0): 2.2预编译安装(Linux-x86_64, CUDA 11.x, ONNX): 3.mmseg工程torch转onnx 4.使用onnx模型文件进行推理…

Dubbo框架学习(第一章Dubbo简介)

由于在微服务领域有两大框架统治,一个是springCloud的全家桶,一个是Dubbo。我用Dubbo比较少,所以也是学习状态。Dubbo框架学习,资料来源于cn.dubbo.apache.org。第一章Dubbo简介Apache Dubbo 是一款 RPC 微服务框架,提…

字节跳动青训营--前端day2

文章目录前言一、css1. css的组成2. css三种使用方式3.css的工作方式二、 css选择器Selector1. 选择元素的方式2. 伪类(pseudo-classes)2.1 状态伪类2.1 结构伪类3.通过组合选择元素3.1 直接组合3.2 元素组合的拓展4. 选择器的特异度(Specifi…

小型水库雨水情测报和安全监测解决方案

平升电子小型水库雨水情测报和安全监测解决方案辅助水利管理部门实现水库雨水情信息“全要素、全量程、全覆盖”自动测报。系统具备水库水位、雨量、现场图像/视频等水文信息采集、传输、处理及预警广播等功能,有效提升了雨水情信息的时效性和准确度,为保…

jmeter 使用beanshell 编写脚本

一、介绍 1.1 介绍 BeanShell是一个小型的、免费的、可嵌入使用Java编写的具有对象脚本语言特性的Java源码解释器。 动态执行所有Java语句、Java代码片段以及弱类型Java和附加的脚本的便利 透明地访问所有Java对象和API 四种运行模式:命令行、控制台、Applet、远…

数据结构专题 -- 哈希思想详解

代码会存放在: https://github.com/sjmshsh/Data-Struct-HandWriting 通过阅读本篇文章,你可以学到: 哈希思想及其本质使用C实现简易的哈希表哈希思想的应用 位图布隆过滤器哈希切分极致升华,海量数据处理面试题 拓展 – 一致性…

二叉树的应用——哈夫曼树

哈夫曼树与哈夫曼编码 1.树的带权路径长 百分制成绩转五级制的算法流程图(A/B/C/D/E的人数分别为6/18/21/36/19)带权路径长 路经长 x 权重 树的带权路经长:所有叶结点的带权路径长度之和。 例如: (a)图…

[ 攻防演练演示篇 ] 利用谷歌 0day 漏洞上线靶机

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…

橘子学kafka之基础命令使用

本系列主要开始处理关于kafka的一些技术知识点,尽量会以代码和实际命令为主要表达形式来做表现。 本文主要是关于如何在客户端使用命令做一个描述,其实我本来不想写的,但是今天在公司有同事居然不会,所以我觉得还是描述一下。而且…

贪心算法合集

95 分糖果问题 思路非常简单,和题解一模一样: 用数组存每个人对应的糖果数量,初始为1 从左到右遍历,如果比左边的大,1再从右到左遍历,如果比右边的大,1 import java.util.*;public class Solu…

录屏大师电脑版推荐(一键录制声画同步的视频)

很多小伙伴使用电脑多年,却不知道电脑有录屏功能。想要对电脑屏幕进行录制,只需在电脑上安装一个录屏大师。那有没有录屏大师电脑版推荐呢?在试用了多款电脑录屏大师之后,小编今天给大家推荐一款可以一键录制声画同步视频的录屏大…

使用Python为二年级的学生批量生成数学题

文章目录一.使用Python为二年级的学生批量生成数学题1.1 背景二.解决思路及其代码三.排版及其打印四.本文源码一.使用Python为二年级的学生批量生成数学题 1.1 背景 我妹妹今年上二年级,她的老师今天给他们布置了一项作业: 从今天起到开学,…

ENSP的AR40问题解决

AR40以及其他相关问题都可以参考此方法,都已经可以正常使用 现在有enspAR40问题的同学有救了,ensp的AR40问题困扰了我很长时间,根据官方的问题解决文档没有解决,反正就是之前的所有方法都没有用,也不是都没有用&#x…

初读《编程之美》就想秀一下,结果还翻车了

文章目录 一、前言 二、我的思路 三、Code 四、翻车现场 五、后续问题 一、前言 ———如何写一个短小的程序,让 Windows 的任务管理器显示CPU的占用率为50%? 这道有趣的面试题我是这两天从《编程之美》电子版中看到的,看意思就是邹老师在微软对一…

入门postgre sql(PG的下载和安装,包括普通用户源码构建的安装方式)

目录PG的下载安装1、Windows 上安装2、Linux上安装有root权限的安装无root权限的安装PG的下载安装 点击这里,了解pg 1、Windows 上安装 (1)下载安装 访问官网下载地址 https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 下载最新发布的Po…

3.kafka-3.生产者,消费者

文章目录1.个性化配置,增加吞吐量2.发送事务消息3.消费组手动提交offset指定offset位置进行消费指定时间消费当新增消费者,或者消费组时,如何消费漏消息和重复消息如何解决消费解压问题1.个性化配置,增加吞吐量 private static vo…

使用 .NET 7、Blazor 和 .NET MAUI 构建你自己的 Podcast App

.NET Podcast App 首次在 .NET Conf 2021上推出,最近进行了更新以在 .NET Conf 2022 keynote 中突出显示 .NET 7 中的新功能。该 Podcast App 已准备好使用展示 .NET,ASP.NET Core,Blazor,.NET MAUI,Azure Container A…

Android 蓝牙开发——概述(一)

一、蓝牙简介 蓝牙技术是一种无线数据和语音通信开放的全球规范,它是基于低成本的近距离无线连接,为固定和移动设备建立通信环境的一种特殊的近距离无线技术连接。 其中将1.x~3.0之间的版本称之为经典蓝牙,4.x开始的蓝牙称之为低功耗蓝牙&…

Memcache学习总结

这里写自定义目录标题介绍一致性哈希寻找节点一致性哈希介绍内存管理slab结构寻找存储chunkChunk中存储的Item数据结构grow factor 调优回收删除一些特性介绍 基于内置内存Key-Value形式存储数据(字符串、对象)集群服务器是通过数组链表方式存储K-V数据<分布式>基于哈希…