一篇文章就足够解决大数据实时面试

大数据实习面试题详解

··by suki

Kafka参数调优的注意事项

  1. 监控和了解系统瓶颈:在调优之前,首先要监控和了解系统的瓶颈。通过监控Kafka的各项指标,如吞吐量、延迟、堆积情况等,可以确定哪些参数需要进行调优。
  2. 确定目标和需求:在调优之前,明确目标和需求非常重要。考虑业务需求、数据量、消息大小、可用资源等因素,以便选择正确的参数来满足需求。
  3. 考虑硬件配置:Kafka的性能受到硬件配置的影响。确保Kafka运行在足够的内存、磁盘和网络带宽上,并避免资源争用问题。
  4. 配置文件调优:Kafka的配置文件(server.properties)包含了很多参数,可以对其进行调整。关注一些重要的参数,如broker数量、分区数量、副本数量、批处理大小、最大网络连接数等,根据需求合理设置这些参数。
  5. 分区和副本配置:根据负载和可用资源,合理分配分区和副本。较少的分区和副本数量有助于提高写入性能,但可能降低消费性能。
  6. 堆内存和文件描述符限制:对于较大的Kafka集群,堆内存的分配和文件描述符限制是需要注意的。根据集群规模和消息大小,调整JVM堆内存大小,并确保操作系统的文件描述符限制足够高。
  7. 生产者和消费者参数设置:根据不同的使用场景,生产者和消费者端也有一些参数可以调优,如acks参数、batch.size、linger.ms等。根据需求选择合适的参数来平衡吞吐量和延迟。
  8. 定期优化和测试:Kafka的负载和需求可能会随时间变化,因此定期进行性能测试和参数调优是必要的。通过监控和测试,及时发现问题并进行调整。

请注意,Kafka参数调优并非一劳永逸的过程,需要根据实际情况进行持续的监控和调整。在调优过程中,建议先进行小范围的测试和验证,再逐步扩大规模和负载,以确保系统的稳定性和可靠性。

Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");       
props.put("group.id", "test");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("auto.offset.reset", "earliest");
props.put("session.timeout.ms", "30000");
props.put("fetch.min.bytes", "1048576");
props.put("fetch.max.wait.ms", "2000");
props.put("max.partition.fetch.bytes", "2097152");
props.put("max.poll.records", "10000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);

Kafka生产者如何实现幂等性写入和事务 &Kafka的producer如何实现幂等性?

答:

首先什么是幂等性? Kafka作为分布式MQ,大量用于分布式系统中,如消息推送系统、业务平台系统(结算平台)等,就拿结算来说,业务方作为上游把数据打到结算平台,如果一份数据被计算、处理了多次,产生的后果将会特别严重。

其次那些因素影响幂等性?使用Kafka时,需要保证exactly-once语义。要知道在分布式系统中,出现网络分区是不可避免的,如果Kafka broker 在回复ack时,出现网络故障或者是Full gc导致ack timeout,producer将会重发,如何保证producer重试时不造成重复or乱序?又或者producer 挂了,新的producer并没有old producer的状态数据,这个时候如何保证幂等?即使Kafka 发送消息满足了幂等,consumer拉取到消息后,把消息交给线程池workers,workers线程对message的处理可能包含异步操作,又会出现以下情况:

  • 先commit,再执行业务逻辑:提交成功,处理失败 。造成丢失
  • 先执行业务逻辑,再commit:提交失败,执行成功。造成重复执行
  • 先执行业务逻辑,再commit:提交成功,异步执行fail。造成丢失

因此Kafka在0.11版新增了幂等型producer和事务型producer。前者解决了单会话幂等性等问题,后者解决了多会话幂等性。

单会话幂等性 为解决producer重试引起的乱序和重复。Kafka增加了pid和seq。Producer中每个RecordBatch都有一个单调递增的seq; Broker上每个tp(主题分区)也会维护pid-seq的映射,并且每Commit都会更新lastSeq。这样recordBatch到来时,broker会先检查RecordBatch再保存数据:如果batch中 baseSeq(第一条消息的seq)比Broker维护的序号(lastSeq)大1,则保存数据,否则不保存(inSequence方法)。

多会话幂等性 事务指的是在跨多个Kafka主题或分区上进行的一组操作,这些操作具有原子性,即要么全部成功,要么全部失败。因此,Kafka生产者可以使用事务来确保消息发送具有原子性和一致性。kafka事务引入了transactionId (事务id)和Epoch(时代),设置transactional.id后,一个transactionId只对应一个pid, 且Server 端会记录最新的 Epoch 值。这样有新的producer初始化时,会向TransactionCoordinator发送InitPIDRequest请求, TransactionCoordinator 已经有了这个 transactionId对应的 meta,会返回之前分配的 PID,并把 Epoch 自增 1 返回,这样当old producer恢复过来请求操作时,将被认为是无效producer抛出异常。 如果没有开启事务,TransactionCoordinator会为新的producer返回new pid,这样就起不到隔离效果,因此无法实现多会话幂等。

注意:

  • 消费者必须设置isolation.level参数为read_committed,以读取只有提交事务的消息。
  • 如果使用了幂等性写入和事务,需要同时开启两种功能,以确保数据的完整性和一致性。
  • 事务API对Kafka的可用性和性能都有一定的影响,因此需要谨慎使用。

Kafka的ISR和OSR的作用分别是什么?

答:ISR(In-Sync Replica,同步副本)和OSR(Out-of-Sync Replica,异步副本)是Kafka中副本状态的概念,它们的作用如下:

  1. ISR(In-Sync Replica):ISR是指已经与Leader副本保持同步的副本集合。只有处于ISR中的副本才能参与到Leader选举以及消息的读写操作中。ISR中的副本会与Leader保持一致的复制进程,这样可以保证数据的可靠性和一致性。

ISR的作用:

  • 数据可靠性:只有ISR中的副本完成了对消息的复制,才被认为是可靠的,确保了数据不会丢失。
  • 高可用性:ISR中的副本可以在Leader副本出现故障时,成为新的Leader副本,确保了服务的持续可用性。
  • 读写性能:ISR中的副本都与Leader副本进行了数据同步,可以提供更高性能的读写操作。
  1. OSR(Out-of-Sync Replica):OSR是指尚未与Leader副本保持同步的副本集合。这些副本可能由于网络延迟、硬件故障或其他原因导致与Leader副本的数据不完全一致。

OSR的作用:

  • 数据冷备份:OSR中的副本作为冷备份,可以在ISR中的副本出现故障时,加入同步副本集并恢复数据,提高可用性。
  • 同步补偿:当OSR中的副本追赶上Leader副本的进度后,可以重新加入ISR,保证数据的一致性。

需要注意的是,ISR和OSR的机制可以根据配置进行调整,以平衡数据的可靠性和性能。通过合理设置ISR大小、最小同步副本数等参数,可以根据业务需求来权衡消息的复制延迟和可用性。

Kafka的producer如何实现幂等性?

⾸先,需要在创建kafka producer时配置其属性来启⽤幂等性,将“acks”设置为‘all’这⾥表⽰所有的ISR都要确认消息写⼊才被认为是成功。这个操作是为了确保消息不会丢失,其次将enable.idempotence设置为‘true’启动幂等性。

实现⽅式主要是通过PID(producerid)和sequenceNum(SN),每个producer初始化的时候,会被分配⼀个唯⼀的PID,然后对于每个PID,producer发送数据的每个Topic和Partition都对应⼀个从0开始单调递增的SN值,每次Partition接收到数据之后会对⽐本⾝存放的sn号和⽣产者发送数据携带的sn号,有以下⼏种情况:
情况1:⽣产者sn<=分区记录sn --数据重复发送,分区拒绝写⼊数据
情况2:⽣产者sn-分区记录sn=1,直接写⼊{只会接受这种数据}
情况3:⽣产者sn-分区记录sn>1,丢失数据,乱序
虽然可以解决数据重复发送的问题,但是消息不能跨分区发送,发送的数据必须和分区绑定(见第二题)

Kafka消费者位置提交⽅式有哪些?分别什么场景下使⽤?

手动提交

⼿动提交是最灵活的⽅式之⼀,适⽤于需要精确控制位移提交情况。这种⽅式下消费者通过调⽤?
commitSync() 或? commitAsync() ⽅法⼿动提交位移。

优点:
可以确保精确的位移控制,避免重复消费和消息丢失。
适⽤于需要处理消息后才提交位移的情况,以确保消息被完全处理后再提交。

缺点:
需要额外的代码来处理位移提交,可能会增加代码复杂性。
如果不⼩⼼,可能导致位移提交失败或不正确,需要更多的错误处理逻辑。

⾃动提交位移(默认)

⾃动提交位移适⽤于那些可以容忍⼀定程度的消息重复和消息丢失的情况。在这种⽅式下,消费者会⾃动定期提交位移。

优点:
减少了位移提交的代码复杂性,减轻了开发负担。
适⽤于不需要强制精确位移控制的情况,可以容忍⼀些不确定性。

缺点:
可能会导致消息重复消费或消息丢失,因为位移提交是异步的,不与消息处理同步。
不适⽤于要求精确位移控制的应⽤程序。

3.⾃动提交位移的⼿动触发

这是⼀种折衷的⽅式,适⽤于希望⾃动提交位移但需要在消息处理之后⼿动触发提交的情况。在这
种⽅式下,消费者会⾃动跟踪位移,但你可以选择在适当的时候⼿动触发位移提交。

优点:
允许⾃动位移提交,减轻了⼀部分位移管理的⼯作。
同时提供了⼿动位移提交的灵活性。

缺点:
仍然可能导致消息重复消费或消息丢失,因为⼿动触发的时机可能不完美。

Kafka消息丢失场景有哪些?如何避免?

⽣产者发送消息时数据丢失

消息⽣产者没有成功发送到Broker:

​ 在同步模式下,有三种状态保证消息被安全⽣产,但是在配置为1(只保证写⼊Leader成功)的话,如果刚好Leader Partition挂了,数据就会丢失

​ 在异步模式下,当缓冲区满了,如果配置为0(还没有收到确认的情况下,缓存池满了,就清空缓冲池⾥的消息,数据就会被⽴即丢弃)

出现异步发送,可加⼊部分同步策略,将确认机制设置为-1.也就是让消息写⼊Leader和所有的副本

Broker多副本同步丢失数据

当ACK=1时,producer发送异步消息完,只等待Leader写⼊成功就返回了,Leader崩溃了,这时ISR中没有Follower,Leader从OSR中选举,因为OSR中本来落后Leader造成消息丢失。配置ACK=all或-1,producer发送消息完,等待Follower同步完再返回,如果异常则重试

消费者消费数据时丢失数据

消费者获取到消息,但消费者还没来得及处理宕机了,但此时kafka中消息已经删除,消费者不能再消费之前的消息

设置autocommit=false,不⾃动提交,通过offset commit来保证数据的不丢失,kafka⾃⼰记录了每次消费的offset数值,下次继续消费的时候,接着上次的offset进⾏消费即可。

消费者未提交偏移量

当消费者成功处理消息但未提交偏移量时,消息可能会被视为未处理⽽重新传递确保消费者使⽤适当的偏移量管理,如⼿动提交偏移量。这可以确保消息被处理后偏移量被更新。

Kafka消费组重新平衡流程

重平衡可以分为两个步骤:加入组和等待领导者消费组。这两个步骤分别对应两个特定的请求:joinGroup请求和syncGroup请求。

当组内成员加入组时,他会向协调者发送joinGroup请求。在该请求中,每个成员都要将⾃⼰订阅的主题上报,这样协调者就能收集到所有成员的订阅信息。⼀旦收集了全部成员的joingroup请求后,协调者会从这些成员中选择⼀个担任这个消费者组的领导者。

这种情况下,第⼀个发送joingroup请求的成员⾃动成为领导者。这⾥的领导者是具体的消费者实例,他既不是副本,也不是协调者。领导者和消费者的任务是收集所有成员的订阅信息,然后根据这些信息,制定具体的分区消费分配⽅案。

选出领导者之后,协调者会把这些消费者组订阅信息封装进joingroup请求的响应体中,然后发送给领导者,由领导者统⼀做出分配⽅案后,进⼊到下⼀步:SyncGroup请求。

在这⼀步中,领导者向协调者发送syncGroup请求,将刚刚做出的分配⽅案发给协调者。在这⾥,其他成员也会向协调者发送syncGroup请求,只不过请求体中并没有实际的内容。这⼀步的主要⽬的是让协调者接收分配⽅案,然后统⼀以syncGroup响应的⽅式分发给所有成员,这样组内所有的成员就知道⾃⼰该消费哪些分区了。

Kafka消费者分区分配策略

消费者分区分配策略是指决定每个消费者实例如何分配订阅的主题分区的⽅式。这些策略可以影响消费者的负载均衡、故障恢复和并⾏处理。

Round Robin轮询分区分配策略:

在这种策略下,消费者依次选择订阅的主题中的每个分区进⾏消费。当新的消费者加⼊群组或者有消费者离开群组时,分区会重新分配,但会保持相对均衡。它的优点简单,均衡地分配分区给不同的消费者,适⽤于具有相似处理能⼒的消费者。但是不考虑分区的数据量和复杂性,可能导致不均匀的负载。

Range范围分区分配策略:

在Range分区分配策略中,每个消费者负责处理⼀组连续的分区范围,通常是⼀些连续的分区编号。例如,⼀个消费者可能处理分区1到5,另⼀个处理分区6到10,以此类推。适⽤于分区数据量差异较⼤的情况,可以有效实现负载均衡。但是如果数据在分区中分布不均匀,仍然可能导致不均匀的负载。

Sticky粘性分区分配策略:

Sticky分区分配策略旨在确保在⼀段时间内,每个消费者尽量分配到相同的分区,以减少消费者切换分区的频率。消费者在⼀段时间内保持与特定分区的"黏性"。有助于减少不必要的分区重新分配,有利于性能。但是可能导致不均衡,特别是在某些消费者处理速度慢的情况下。

Kafka&Flink&ClickHouse在联合场景中的优势

在实时数据采集和传输⽅⾯:

kafka作为消息中间件可⽤于实时数据采集和传输。你可以将数据⽣产者
(如应⽤程序、传感器、⽇志⽂件等)与Kafka集成,以将数据流式传输到Kafka主题中。Kafka提供了⾼吞吐量和持久性,确保数据的可靠传输。

在实时流处理⽅⾯:

Flink可以订阅Kafka主题中的数据流,并提供强⼤的实时流处理功能。可以使⽤
Flink进⾏数据转换、过滤、聚合、窗⼝化等操作,以实时分析和处理数据。Flink⽀持处理复杂事件模式、处理乱序事件以及执⾏实时ETL等。

实时数据存储和分析:

ClickHouse作为列式数据库管理系统,可以⽤于存储和分析实时处理后的数
据。可以将Flink处理后的数据写⼊ClickHouse,以进⾏实时查询、数据分析和仪表盘制作。
ClickHouse具有⾼性能、压缩存储和分布式能⼒,适⽤于⼤规模数据分析。

低延迟数据处理:

结合这三个⼯具,你可以实现低延迟的数据处理。Kafka确保了数据的快速传递,
Flink执⾏实时处理,⽽ClickHouse可以迅速响应查询请求,使你能够进⾏快速的实时数据分析。

实时监控和报警:

可以使⽤Flink来实时监控数据流,检测异常或特定事件模式,并在需要时触发报
警。同时,ClickHouse的查询结果可以⽤于实时监控仪表盘。

容错性和可伸缩性:

可以根据需求扩展Kafka集群、Flink任务管理器和ClickHouse节点,同时它们都
⽀持副本和分布式部署,以确保容错性。

ClickHouse中的ReplicatedMergeTree是什么?有什么优点?

ReplicatedMergeTree是MergeTree的派⽣引擎,它在MergeTree的基础上加⼊了分布式协同的能⼒,只有使⽤了ReplicatedMergeTree复制表系列引擎,才能应⽤副本的能⼒。或者⽤⼀种更为直接的⽅式理解,即使⽤ReplicatedMergeTree的数据表就是副本。

ReplicatedMergeTree基础之上增加了Zookeeper的部分,也就是在Zookeeper内创建⼀系列的监听节点,以此实现多个实例之间的通信。但在整个通信中,Zookeeper不会涉及数据的传输。

特点:

依赖Zookeeper:在执⾏insert和alter查询的时候,ReplicateMergeTree需要借助Zookeeper的分布式协同能⼒,已实现多个副本之间的同步

表级别的副本:副本是在表级别定义的,所以每张表的副本配置都可以按照它的实际需求进⾏个性化定义,包括副本的数量,以及副本在集群内的分布位置

多主架构L可以在任意⼀个副本上执⾏insert和alter查询,效果是相同的。这些操作会借助
Zookeeper的协同能⼒被分发⾄每个副本以本地形式执⾏?
原⼦性:在数据写⼊的时候,⼀个Block块内的数据要么全部写⼊成功,要不全部失败

ClickHouse的分布式查询流程是什么样的?

⾸先会借助分区索引,clickhouse通常会将数据按照时间分为不同的分区,每个分区都包含⼀段时间内的数据。(这种时间分区有助于查询数据时仅扫描特定时间范围内的分区,从⽽降低数据范围。当执⾏查询时,数据库系统可以根据查询条件确定需要检索的分区,并只访问这些分区,⽽不必扫描整个表)

clickhouse⽀持主键索引(⼀级索引)和其他字段的索引(⼆级索引)。主键索引通常⽤于快速查找具有唯⼀标识符的⾏。⼆级索引可以⽤于加速根据其他列的过滤和排序。(当查询包括过滤条件时,数据库系统可以使⽤适当的索引来快速定位到匹配条件的数据⾏,从⽽避免扫描整个表。进⼀步缩⼩了需要处理的数据范围)

clickhouse使⽤数据标记策略来标记哪些数据需要进⾏特定的处理这种处理可以包括解压缩或计算。在查询过程中,只有被标记的数据才会进⾏额外的处理。(在执⾏聚合操作的时候,只有相关数据块被标记为需要聚合的数据才会被处理,⽽其他数据块不会浪费计算资源)

谓词下推是⼀个关键的查询优化策略。也就是说将查询中的过滤条件尽早地应⽤于数据,以减⼩数据范围。

就⽐如说⼀个包含⼤量电⼦商务订单的ClickHouse表每个订单包括订单号、订单⽇期、客⼾ID、商品ID等信息,需要执⾏⼀个查询,以查找特定⽇期范围内特定客⼾的订单数量。

⾸先选择时间范围,然后利⽤分区索引,由于clickhouse通常是按时间分区数据,⾸先使⽤分区索引来确定包含所选⽇期范围的分区,(例如,如果查询的⽇期范围在三个不同的分区内,只需要选择这三个分区的数据)
接下来,将⽇期范围的过滤条件尽早应⽤于数据,进⼀步减⼩数据范围。(这个操作筛选出不符合条件的数据块)

利⽤客⼾ID的⼆级索引,如果客⼾ID是⼀个经常⽤于查询的字段,并且有相应的⼆级索引,可以使⽤该索引来快速定位到特定客⼾的订单
数据标记和解压缩,⼀旦确定了需要的数据块,数据库系统会标记和减压这些数据块
在获取数据块后,应⽤其他过滤条件(商品ID)或执⾏聚合操作以获取所需的结果。

ClickHouse存储结构及优势

Clickhouse使⽤列式存储,将每个列独⽴存储在磁盘上,⽽不是将每⾏作为⼀个单独的存储单元,他的主要存储引擎是MergeTree,他⽀持时间序列数据的⾼效存储和查询,MergeTree以分区,排序和索引的⽅式组织数据,可以快速执⾏范围查询和聚合操作。

  1. 列式存储:ClickHouse将每个列独立存储,相同数据类型的值连续存储在一起。这种列式存储方式使得数据的压缩和查询更加高效,因为它提供了更好的数据局部性和压缩率。
  2. 分区和排序:ClickHouse支持对数据进行分区和排序,即使在大规模数据集下也可以保持高性能。数据分区和排序能够减少磁盘I/O的数量,并且在查询时允许跳过不必要的数据。
  3. 压缩:ClickHouse使用了多种压缩算法对数据进行压缩,以减小存储空间的占用。它根据列数据的特点选择合适的压缩算法,并在查询时进行解压缩,从而提高查询效率。
  4. 数据索引:ClickHouse使用Bloom Filter等索引技术来加速查询过程。索引能够减少不必要的数据访问,提供更快的查询响应时间。

他还使⽤多种的数据压缩算法,⽐如delta,以减⼩数据占⽤的存储空间,减少磁盘IO和⽹络传输成本,并且⽀持多种索引,⽐如稀疏索引,加速数据的检索和过滤操作。其中的数据可以按照分区键进⾏划分,以⽀持时间序列数据的快速插⼊和查询。

优势:

  1. 高性能:列式存储结构使得ClickHouse在数据分析、聚合和查询方面具有出色的性能。通过读取和处理列而不是整行数据,可以减少磁盘I/O和内存消耗,提高查询速度。
  2. 高扩展性:ClickHouse是一个分布式数据库,可以通过在多个节点上并行处理数据,实现水平扩展。它支持数据的分片和副本复制,保证了数据的可靠性和高可用性。
  3. 良好的压缩率:由于采用了列式存储和适应列类型的压缩算法,ClickHouse可以显著减小数据的存储空间,在存储大规模数据时具有很大的优势。
  4. 强大的查询功能:ClickHouse支持丰富的查询语法和灵活的聚合功能,可以执行复杂的分析查询。它还提供了高性能的并行查询执行引擎,使得大规模数据的查询变得更加高效和快速。

ClickHouse各种索引的区别和使用场景

  1. 主键索引(Primary Key Index):
  • 区别:主键索引是最基本的索引类型,用于唯一标识每一行数据。主键索引会对主键列进行排序,以支持快速的范围查询和唯一性约束。
  • 使用场景:适用于需要根据主键进行唯一标识和范围查询的场景,例如按时间范围查询、按用户ID查询等。
  1. 排序索引(Sorting Key Index):
  • 区别:排序索引在主键索引的基础上,通过额外的排序列进一步优化查询性能。排序索引将数据按照指定的排序列进行物理排序存储,从而加快范围查询和特定顺序查询的速度。
  • 使用场景:适合需要按照特定顺序进行查询或范围查询的场景,例如按照时间顺序查询最新的数据、按照字母顺序查询名称等。
  1. 字典索引(Dictionary Index):
  • 区别:字典索引使用一个字典对列中的值进行编码,并将编码后的值存储在索引中。这样可以减小索引的大小,提高查询性能和压缩率,但会增加编码和解码的开销。
  • 使用场景:适用于列中具有较少不同值的情况,例如性别、地区等。字典索引可以显著减小索引大小,提高查询性能。
  1. Range Index(范围索引):
  • 区别:范围索引是一种基于范围的数据结构,用于对范围查询进行优化。它将数据分成多个范围,每个范围维护一个索引结构,以支持快速的范围查询。
  • 使用场景:适用于大规模数据集和范围查询比较频繁的场景,例如时间段内的数据查询、数值范围过滤等。
  1. Bitmap Index(位图索引):
  • 区别:位图索引使用位图表示多个列的不同取值,以加快多列条件查询的速度。位图索引在查询时对比位图来确定符合给定条件的行。
  • 使用场景:适用于多列条件查询较为频繁的场景,例如根据用户属性和地理位置进行查询等。

ClickHouse查询性能优化

​ 当优化ClickHouse的查询性能时,可以采取以下详细措施:

  1. 数据模型设计优化:
    • 使用最合适的数据类型:选择合适的数据类型可以减小存储空间、提高内存效率和查询性能。例如,使用较小的整数类型代替大整数类型、使用FixedString代替可变长度字符串等。
    • 数据冗余和压缩:通过冗余存储和压缩算法来降低存储占用和提高查询速度。冗余存储是指在多个列中存储相同的数据,以加快特定查询的速度。压缩算法能够减小数据文件的大小,并提高磁盘I/O性能。
  2. 适当的数据分区和排序键:
    • 数据分区:根据查询模式和业务需求选择合适的数据分区方式。ClickHouse支持按范围、日期、哈希等多种分区方式。合理的数据分区可以减少不必要的数据扫描和过滤,提高查询速度。
    • 排序键:定义适当的排序键以优化查询性能。排序键决定了数据在磁盘上的物理顺序,使得范围查询和特定顺序查询更加高效。
  3. 调整查询语句和查询引擎设置:
    • 减少不必要的列和行:只查询需要的列,避免拉取不相关的数据。使用WHERE子句进行条件过滤,以减小返回结果的大小和提高查询速度。
    • 使用合适的聚合函数:根据需求选择最适合的聚合函数,避免在查询结果后再进行额外的聚合计算。ClickHouse内置了各种聚合函数,如SUM、COUNT、AVG等。
    • 设置合理的查询引擎参数:调整查询引擎的并发度、内存限制、合并策略等参数,以匹配硬件资源和查询负载。例如,可以调整max_threads参数来控制并发查询的数量。
  4. 使用合适的索引:
    • 主键索引和排序索引:主键索引用于唯一标识每一行数据,并支持快速的范围查询。排序索引在主键索引的基础上,通过额外的排序列进一步优化查询性能。根据查询需求选择合适的索引类型。
    • 字典索引和位图索引:字典索引使用编码后的值来减小索引大小,提高查询性能。位图索引用于多列条件查询,以加快多列条件匹配的速度。
  5. 数据预热和缓存优化:
    • 提前加载数据到缓存:通过定期或按需将数据加载到内存缓存中,可以减少磁盘I/O读取的次数,提高查询速度。
    • 调整缓存设置:根据内存资源和查询需求,适当调整ClickHouse的缓存设置。可以调整max_memory_usage参数来控制每个查询的内存使用量。
  6. 分布式查询优化:
    • 合理分片和副本设置:根据数据规模和查询负载,选择合适的数据分片和副本设置。将数据分散在多个节点上,可以实现负载均衡和高可用性。
    • 并行查询设置:根据硬件资源和查询需求,调整并行查询的数量和设置。适当增加并行度可以提高查询吞吐量。

Flink任务链和任务槽的作用是什么?

Flink任务链(Task Chaining)和任务槽(Task Slots)是作用于Flink作业执行的两个重要概念。

  1. 任务链:任务链是将相邻的算子(Operator)合并为一个任务执行的机制。在任务链中,多个算子被串联在一起形成一个任务,数据可以通过内部迭代器直接传递,减少了数据的序列化和反序列化开销,提高了整体执行速度。任务链可以减少网络传输开销和中间数据的存储,尤其在迭代计算和有界流处理场景下有明显优势。使用任务链时,需要确保算子之间没有数据分区(Data Partitioning)的操作,避免打破任务链。
  2. 任务槽:任务槽是Flink任务调度和资源管理的基本单位。一个任务槽可以执行一个或多个Flink算子,并且可以并发执行多个任务槽。每个任务槽都有一定的资源配额,如CPU、内存等。任务槽的数量和资源配额根据集群配置进行分配。任务槽可以用来控制并发度,同时也可以用于隔离不同的任务。任务槽的数目与集群资源的关系密切,合理利用任务槽可以提高作业的并发度和整体执行效率。

任务链和任务槽的作用如下:

  • 任务链可以减少数据的序列化和反序列化开销,提高整体执行速度,并在特定场景下显著降低网络传输和中间数据存储的开销。
  • 通过设置合适的任务槽数目和资源配额,可以灵活控制Flink作业的并发度和资源利用率。
  • 任务链和任务槽结合使用,能够优化Flink作业的执行效率,提高数据处理的吞吐量和延迟。

需要注意的是,在使用任务链时需要考虑算子之间的依赖关系、数据分区以及内存等资源的限制,避免因任务链导致的资源争用或数据倾斜等问题。同时,任务链和任务槽的配置也需要根据具体的作业需求和集群资源情况进行调优。

Flink SQL和Table API的区别是什么?

Flink SQL和Table API是Apache Flink提供的两种用于处理数据的高级API,它们有以下区别:

  1. 表达方式:Flink SQL使用类似于传统SQL的表达式来处理数据,可以直接编写SQL语句进行查询、过滤、聚合等操作。而Table API则是一种基于函数式编程的API,通过编写代码来操作和转换表。
  2. 编程风格:Flink SQL更加声明式,将关注点放在了数据的逻辑处理上,隐藏了底层的细节。而Table API更加命令式,需要显式地定义对表的操作和转换。
  3. 学习曲线:对于熟悉SQL的开发人员来说,使用Flink SQL更为便捷,无需额外学习API。而对于习惯使用编程语言进行开发的人员来说,Table API更加灵活,并且能够进行更多的自定义操作。
  4. 功能支持:Table API相对于Flink SQL来说,具有更强大的编程能力和更灵活的表达方式,能够进行更复杂的数据转换和计算。Flink SQL的功能相对较为有限,适用于常见的数据处理场景。
  5. 调试和优化:由于Flink SQL是基于SQL语句的,对于调试和优化可能会相对困难一些,需要依赖于底层的执行计划。而Table API是基于编程的方式实现的,更容易进行调试和优化。

总的来说,Flink SQL适用于简单的查询和常见的数据处理场景,能够提供更高层次的抽象,简化开发流程;而Table API则更加灵活,适用于复杂的数据转换和计算场景,提供更多的编程能力和自定义选项。选择何种方式主要取决于开发人员的编程偏好、项目需求以及数据处理的复杂程度。另外,Flink SQL和Table API可以互相转化,开发者可以根据具体的需求选择使用。

Flink Streaming如何处理迟到事件?

在乱序流中,⽔位线并不能⼀定保证时间戳更早的数据不会再来,当⽔位线已经到达窗⼝结束时间时,窗⼝会触发计算并输出结果,这时候⼀般就要销毁窗⼝,如果窗⼝关闭后,⼜有本属于窗⼝内的数据姗姗来迟,默认情况下就会被丢失。(也就是某个⽔位线之后到来的数据)

设置⽔位线延迟时间
在Flink中提供了⼀个特殊的接⼝⽅法(.allowedLateness()⽅法),可以为窗⼝算⼦设置⼀个“允许的最⼤延迟”,也就是我们可以设定允许延迟⼀段时间,在这段时间内,窗⼝不会销毁,继续到来的数据依然可以进⼊窗⼝中并触发计算。指导⽔位线推进到了窗⼝结束时间+延迟时间,才真正将窗⼝的内容情况,正式关闭窗⼝。

允许窗⼝处理迟到数据
⽐如说⽔位线延迟设置⽐较⼩,如果之后仍有数据迟到,对于窗⼝计算⽽⾔,到了结束时间就默认关闭窗⼝。由于⼤部分乱序数据已经被⽔位线的延迟等到了,所以迟到的数据应该不会太多。这个时候,我们会在⽔位线到达窗⼝结束时间时,先快速输出⼀个近似正确的计算结果然后保持窗⼝继续等到延迟数据,每来⼀条数据,窗⼝就会再次计算,并将更新后的结果输出。这样就可以逐步修正计算结果,最终得到准确的统计值了。

将迟到的数据放⼊侧输出流
我们可以将未收⼊窗⼝的迟到数据,放⼊“侧输出流”进⾏另外的处理。也就是将本该丢弃的数据单独的放⼊到⼀个流中。基于.sideOutputLateData()?⽅法。需要传⼊⼀个“输出标签”⽤来标记分⽀的迟到数据流。

Flink中数据倾斜原因和解决方案

相同Task的多个subtask中,个别subtask接收到的数据量明显⼤于其他subtask接收到的数据量,我们可以在Flink web UI上看到每个subtask处理了多少数据,即可判断是否出现了数据倾斜。
数据倾斜也会引起反压,checkpoint detail⾥不同subtask的State size也是分析数据倾斜的指标
1.keyby后的聚合操作存在数据倾斜

不能直接使⽤⼆次聚合来处理
如果keyby之后的聚合操作存在数据倾斜,且没有开窗⼝(也就是没有攒下批)的情况下,使⽤两阶段聚合是不能解决问题,因为Flink是来⼀条处理⼀条,向下游发送⼀条结果,对于原来keyby的维度(第⼆阶段聚合)来讲,数据量并没有减少,且结果重复计算

使⽤LocalKeyby思想
在keyBy上游算⼦数据发送之前,⾸先在上游算⼦的本地对数据进⾏聚合,在发送到下游,使下游接收到的数据量减少,从⽽使得keyBy之后的聚合操作不再是任务的瓶颈。类似于MapReduce中的combiner思想。

具体的实现⽅式
DataStream API:在keyBy之前开窗⼝做预聚合聚合
FlinkSQL API:开启miniBatch和LocalGlobal功能

2.keyBy之前发⽣数据倾斜
如果在keyBy之前就存在数据倾斜,上游算⼦的某些实例可能处理的数据较多,某些实例可能处理的数据较少,产⽣该情况的原因就是因为数据源的数据本⾝就不均匀,例如由于某些原因kafka的topic中某些Partition的数据量较⼤,某些Partition的数据量较少。对不存在keyBy的Flink任务也会出现这种情况
可以使⽤shuffle,rebalance算⼦将数据均匀分配,从⽽解决数据倾斜的问题。

3.keyBy后的窗⼝聚合操作存在数据倾斜
因为使⽤了窗⼝,变成了有界数据(攒批)的处理,窗⼝默认是触发时才会输出结果发往下游,可以使⽤两阶段聚合
第⼀阶段:key拼接随机数前缀或后缀,进⾏keyby,开窗,聚合
第⼆阶段:按照原来的key以及windowEnd作keyby,聚合。

Flink内存模型与内存优化

Flink 的内存模型由三个主要组件组成:JVM 堆内存、堆外内存和操作系统内存(例如文件系统缓存)。其中,JVM 堆内存被用来存储 Flink 任务中的 Java 对象,包括数据流、状态和函数对象等。堆外内存则主要用于存储 Flink 中的网络、序列化和 I/O 等资源。操作系统内存则用于缓存数据和文件读写。

FlinkJVM进程的进程总内存包含了Flink应⽤使⽤的内存和运⾏Flink的JVM使⽤的内存。Flink总内存包括JVM堆内存和堆外内存。其中堆外内存包括直接内存和本地内存。就⽐如说TaskManager是负责执⾏⽤⼾代码的⻆⾊,⼀般配置TaskManager内存情况较多。

1.建议为Standalone配置Flink总内存,设置JobManager和TaskManager的flink.size⼤⼩,声明为Flink本⾝提供了多少内存

参数配置:
taskManager.memory.flink.size:
jobmanager.memory.flink.size:

2.为containers(容器)配置内存

为容器化部署(yarn)配置总进程内存,设置Process.size⼤⼩,声明了总共应该分配多少内存给Flink JVM进程,并对应于请求容器的⼤⼩

参数配置:
taskManager.memory.process.size:
jobmanager.memory.process.size:

3.为State backends(状态后端)配置内存

这个仅于TaskManager有关,在部署Flink流应⽤程序时,所使⽤的状态后端类型决定集群的最佳内存配置。

3.1为HashMap状态后端
运⾏⽆状态作业或使⽤?HashMapStateBackend时,将托管内存设置为零。这将确保为JVM上的⽤⼾代码分配最⼤数量的堆内存。

配置参数:
设置size:0
taskmanager.memory.managed.size:0

3.2RocksDB状态后端
默认情况下,RocksDB设置为将本机内存分配限制为托管内存的⼤⼩。因此,为你的状态保留⾜够的托管内存⾮常重要。如果禁⽤默认的RocksDB内存控制,RocksDB分配的内存超过请求的容器⼤⼩(总进程内存)的限制,则可以在容器化部署中终⽌TaskManager
为batch Job(批处理作业)配置内存
也是只与TaskManager有关。Flink?的批处理操作符利⽤托管内存来更⾼效地运⾏。这样可以直接
对原始数据执⾏某些操作,⽽⽆需反序列化为?Java?对象。如果托管内存不⾜,Flink?会溢出到磁
盘。

Flink窗口机制有哪些?应用场景分别是什么?

滚动窗口(Tumbling Windows)

将数据依据固定的窗口长度对数据进行切片。

特点:时间对齐,窗口长度固定,没有重叠。

滚动窗口分配器将每个元素分配到一个指定窗口大小的窗口中,滚动窗口有一个固定的大小,并且不会出现重叠。

适用场景:适合做 BI 统计等(做每个时间段的聚合计算)。

滑动窗口(Sliding Windows)
滑动窗口是固定窗口的更广义的一种形式,滑动窗口由固定的窗口长度和滑动间隔组成。
特点:时间对齐,窗口长度固定,有重叠。
滑动窗口分配器将元素分配到固定长度的窗口中,与滚动窗口类似,窗口的大小
由窗口大小参数来配置,另一个窗口滑动参数控制滑动窗口开始的频率。因此,滑动窗口如果滑动参数小于窗口大小的话,窗口是可以重叠的,在这种情况下元素会被分配到多个窗口中。

适用场景:对最近一个时间段内的统计(求某接口最近 5min 的失败率来决定是
否要报警)。

会话窗口(Session Windows)
由一系列事件组合一个指定时间长度的 timeout 间隙组成,类似于 web 应用的session,也就是一段时间没有接收到新数据就会生成新的窗口。
特点:时间无对齐。
session 窗口分配器通过 session 活动来对元素进行分组,session 窗口跟滚动窗口和滑动窗口相比,不会有重叠和固定的开始时间和结束时间的情况,相反,当它在一个固定的时间周期内不再收到元素,即非活动间隔产生,那个这个窗口就会关闭。一个 session 窗口通过一个 session 间隔来配置,这个 session 间隔定义了非活跃周期的长度,当这个非活跃周期产生,那么当前的 session 将关闭并且后续的元素将被分配到新的 session 窗口中去。

总结

  1. flink 支持两种划分窗口的方式(time 和 count)

    如果根据时间划分窗口,那么它就是一个 time-window
    如果根据数据划分窗口,那么它就是一个 count-window

  2. flink 支持窗口的两个重要属性(size 和 interval)
    如果 size=interval,那么就会形成 tumbling-window(无重叠数据)
    如果 size>interval,那么就会形成 sliding-window(有重叠数据)
    如果 size<interval,那么这种窗口将会丢失数据。比如每 5 秒钟,统计过去 3 秒的通过路口汽车的数据,将会漏掉 2 秒钟的数据。

  3. 通过组合可以得出四种基本窗口
    time-tumbling-window 无重叠数据的时间窗口,设置方式举例:
    timeWindow(Time.seconds(5))
    time-sliding-window 有重叠数据的时间窗口,设置方式举例:
    timeWindow(Time.seconds(5), Time.seconds(3))
    count-tumbling-window 无重叠数据的数量窗口,设置方式举例:
    countWindow(5)
    count-sliding-window 有重叠数据的数量窗口,设置方式举例:
    countWindow(5,3)

Flink Savepoint和Checkpoint的区别

**FlinkCheckpoint 是一种容错恢复机制。**这种机制保证了实时程序运行时,即使突然遇到异常也能够进行自我恢复。Checkpoint 对于用户层面,是透明的,用户会感觉程序一直在运行。Flink Checkpoint 是 Flink 自身的系统行为,用户无法对其进行交互,用户可以在程序启动之前,设置好实时程序 Checkpoint 相关参数,当程序启动之后,剩下的就全交给 Flink 自行管理。当然在某些情况,比如 Flink On Yarn 模式,某个 Container 发生 OOM 异常,这种情况程序直接变成失败状态,此时 Flink 程序虽然开启 Checkpoint 也无法恢复,因为程序已经变成失败状态,所以此时可以借助外部参与启动程序,比如外部程序检测到实时任务失败时,从新对实时任务进行拉起。

**Flink Savepoint 你可以把它当做在某个时间点程序状态全局镜像,以后程序在进行升级,或者修改并发度等情况,还能从保存的状态位继续启动恢复。**Flink Savepoint 一般存储在 HDFS 上面,它需要用户主动进行触发。如果是用户自定义开发的实时程序,比如使用DataStream进行开发,建议为每个算子定义一个 uid,这样我们在修改作业时,即使导致程序拓扑图改变,由于相关算子 uid 没有变,那么这些算子还能够继续使用之前的状态,如果用户没有定义 uid , Flink 会为每个算子自动生成 uid,如果用户修改了程序,可能导致之前的状态程序不能再进行复用。

Flink Checkpoint和Savepoint对比:

  1. 概念:Checkpoint 是 自动容错机制 ,Savepoint 程序全局状态镜像 。
  2. 目的: Checkpoint 是程序自动容错,快速恢复 。Savepoint是 程序修改后继续从状态恢复,程序升级等。
  3. 用户交互:Checkpoint 是 Flink 系统行为 。Savepoint是用户触发。
  4. 状态文件保留策略:Checkpoint默认程序删除,可以设置CheckpointConfig中的参数进行保留 。Savepoint会一直保存,除非用户删除 。

Flink与Spark Streaming的技术选型对比

处理模型上:

Flink 采⽤了事件时间(EventTime)处理模型,能够处理乱序事件和⽔位线(Watermark)来确保正确的事件顺序和处理。这使得Flink在处理延迟和乱序数据时表现出⾊。
Spark Streaming 采⽤微批处理模型,将数据流划分为⼩的批次进⾏处理,通常以⼏秒的时间窗⼝为单位。这可能导致⼀定的延迟,特别是在⼩时间窗⼝内。

状态管理上:

Flink内置了强⼤的状态管理功能,允许在有状态的处理中保持和管理状态信息。
Spark Streaming的状态管理相对较弱,通常需要与外部存储(如HDFS)结合使⽤。

语⾔⽀持上:

Flink主要使⽤Java和Scala编写,⽀持Table?API和SQL。(新版本开始遗弃scala)
Spark Streaming⽀持Java、Scala

⽣态系统和扩展上:

Flink⽣态系统相对较⼩,但它有⼀个活跃的社区,不断增加新的连接器和库。它还⽀持连接到其他存储和计算框架,如Kafka、Hive等。
Spark Streaming作为Apache Spark的⼀部分,可以充分利⽤Spark的⽣态系统,包括Spark SQL、MLlib、GraphX等。

部署模式上:

Flink通常在分布式流处理环境下运⾏,可以轻松地在YARN、Kubernetes等上部署。
Spark Streaming通常与Apache Spark⼀起使⽤,⽀持多种部署模式,包括本地模式、YARN和Mesos。

性能上:

Flink通常在低延迟、⾼吞吐量和事件时间处理⽅⾯表现出⾊。
Spark Streaming在⼤数据处理⽅⾯表现出⾊,但在低延迟和事件时间处理⽅⾯可能不如Flink。

Flink内存管理机制及其参数调优?

基本原理

Flink的内存管理机制主要涉及两个方面:JVM堆内存Off-Heap内存。具体来说,Flink在执行过程中会使用JVM堆内存来管理Java对象,而使用Off-Heap内存来管理序列化的数据和其他非Java对象。在Flink中,有如下几种内存管理方式:

  1. Managed Memory:Flink通过预分配JVM堆内存和Off-Heap内存并实现垃圾回收机制来管理内存。这种方式的好处是可靠性高、易于管理,但同时可能会存在较大的内存浪费。
  2. Memory-Mapped Files:Flink使用内存映射文件来管理Off-Heap内存。这种方式的好处是减少了内存浪费,并且可以避免OutOfMemoryError异常,但同时需要考虑文件IO带来的额外开销。
  3. Hybrid Memory:Flink将Managed Memory和Memory-Mapped Files两种方式结合起来使用,可以兼顾两者的优点,但同时需要更复杂的管理策略。

Flink 并不是将大量对象存在堆内存上,而是将对象都序列化到一个预分配的内存块上, 这个内存块叫做 MemorySegment,它代表了一段固定长度的内存(默认大小为 32KB),也是 Flink 中最小的内存分配单元,并且提供了非常高效的读写方法,很多运算可以直接操作 二进制数据,不需要反序列化即可执行。每条记录都会以序列化的形式存储在一个或多个 MemorySegment 中。如果需要处理的数据多于可以保存在内存中的数据,Flink 的运算符会将部分数据溢出到磁盘。

Flink1.11后TM与JM内存配置一样。一共包含 3大部分,分别为总体内存JVM Heap 堆上内存、Off-Heap 堆外内存等。

总进程内存(Total Process Memory) = Flink 总内存 + JVM 元空间 + JVM 执行开销

JVM Heap (JVM 堆上内存) = JVM Heap (JVM 堆上内存) + Task Heap : 任务堆内存

**Off-Heap Mempry(JVM 堆外内存) **= Managed memory: 托管内存 + **DirectMemory:**JVM 直接内存

调优

Standalone 配置内存 taskmanager.memory.flink.size jobmanager.memory.flink.size

Containers(容器) 配置内存 taskmanager.memory.process.size jobmanager.memory.process.size

state backends(状态后端)配置内存 askmanager.memory.managed.size

口诀:

一压二查三指标,延迟吞吐是关键
时刻关注资源量,排查首先看GC

1. JSON序列化与反序列化

常出现在source和sink任务上,在指标上没有体现,容易被忽略

2. Map和set的Hash冲突

由于HashMap,HashSet等随着负载因子增高,引起的插入和查询性能下降。

3. 数据倾斜

数据倾斜会导致其中一个或者多个subtask处理的数据量远大于其他节点,造成局部数据延迟。

4. 和低速系统的交互

在实时系统进行高速数据处理时,当涉及到与外部低俗的系统(如Mysql,Hbase等)进行数据交互时。

5. 频繁的GC

因内存或者内存比例分配不合理导致频繁GC, 甚至是TaskManager失联

6. 大窗口

窗口size大,数据量大,或者是滑动窗口size和step的比值比较大,如size=10minmatch, step=1。

内存调优

Flink的内存主要分为三部分,对于network buffer和manager pool都是由Flink管理的,manager pool也已经走向堆外内存,因此flink 的内存调优主要分为两部分:

a. 非堆内存 network buffer 和 manager poll的调优

b. flink 系统中的heap内存的调优

非堆内存调优

对于非堆内存调优比较简单,主要是调整:network buffer 和manager pool buffer 的比例

1. Networkbuffer:

  • taskmanager.network.memory.fraction (默认是0.1)
  • taskmanager.network.memory.min
    ( 默认是64M)
  • taskmanager.network.memory.max
    (默认是1G)

原则:默认是0.1或是小于0.1,可以根据使用情况进行调整。

2. ManagerBuffer:

  • taskmanager.memory.off-heap:true
    ( 默认是false)
  • taskmanager.memory.fraction
    (默认是0.7)

原则:在流计算中如果用户建议调整成小于0.3

堆内存调优

Flink是运行在jvm上的,故flink应用的堆内存调优和传统jvm调优无差别。

默认Flink使用的Parallel Scavenge的垃圾回收器可以改用G1 垃圾回收期。

启动参数如下:

env.java.opts=-server -XX:+UseG1GC -XX:MaxGCPauseMillis=300 --XX:+PrintGCDetails

Flink任务链和任务槽的作用是什么?

Flink任务链:

Flink任务链是一种优化技术,可以将多个算子(Operator)连成一个长的有向无环图,从而减少数据传输和序列化/反序列化的开销,提高整个任务的执行效率。在一个任务链中,相邻的算子可以共享相同的处理线程,从而避免了线程切换的开销。任务链是在编译时生成的,因此对于动态生成的算子或某些不能合并的算子,任务链无法使用。

任务链可以通过以下方式进行启用或禁用:

  1. 针对特定的算子:在算子配置中设置chainStart和chainEnd参数;
  2. 针对整个任务:在ExecutionConfig中设置enableChaining参数。

Flink任务槽:

Flink任务槽是Flink中资源管理的基本单位。在Flink集群中,每个TaskManager节点通常会被分配多个任务槽,每个任务槽可以运行一个或多个并行度相同的算子,从而实现对资源的灵活分配和控制。任务槽的数量取决于集群的配置和可用资源情况,通常为队列模式(slot sharing mode)或独占模式(exclusive mode)。在队列模式下,多个算子可以共享同一个任务槽,从而节省资源和提高并发度;在独占模式下,则每个算子都会占用一个任务槽,资源更为独立。

任务槽可以通过以下方式进行管理:

  1. 静态分配:在启动集群时,手动配置每个TaskManager节点的任务槽数量;
  2. 动态分配:Flink 1.12版本引入了动态分配任务槽的功能,可以根据作业需要在运行时动态调整任务槽数量,并自动分配到空闲的TaskManager节点。

总体来说,Flink任务链和任务槽是Flink作业执行效率和资源利用的关键因素。在实际开发和应用中,需要结合具体的业务需求和集群配置进行合理的设置和优化,以获取最佳的性能和稳定性。

Flink状态管理内部原理是什么?

Flink状态管理总结 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/587714409)

假设我们有一个电商网站,在这个网站上可以进行商品的浏览、购买、评价等操作。为了便于业务分析和优化,我们需要对用户的行为进行实时统计和分析。具体来说,需要统计每个商品的浏览次数、下单次数、成交金额等指标,并以实时可视化的方式展现出来。

为了实现这一目标,我们可以使用Flink来进行实时计算和数据处理。在程序中,我们需要定义一些状态来记录用户的行为,如:

  • 商品浏览量:记录每个商品的浏览次数;
  • 商品下单量:记录每个商品的下单次数;
  • 商品成交金额:记录每个商品的成交金额;
  • 用户购买记录:记录每个用户的购买记录。

在Flink中,我们可以通过声明和管理这些状态来实现实时计算和分析。具体步骤如下:

  1. 状态的定义:Flink支持不同类型的状态,如键值对状态、列表状态、折叠状态等。用户可以自定义状态的数据结构和计算操作,并在程序中显式声明并使用这些状态。状态的声明通常在程序的开始位置完成,可以用于保存一些需要跨任务和操作保持一致的状态信息。(两种类型的状态:算子状态和键值分区状态)
  2. 状态的管理:Flink将状态分配给不同的任务运行实例进行管理,保证在不同的并行任务之间共享该状态。Flink利用快照机制来保证状态的一致性和恢复。具体来说,Flink定期对状态进行快照(Checkpoint),并将快照写入持久化存储中,以便在发生故障时能够恢复状态。此外,Flink还提供了精细的控制机制,可以让用户自定义快照的触发时间、间隔和一致性模式等参数。
  3. 状态的持久化:为了保证状态在故障发生时不会丢失或损坏,Flink将状态持久化到外部存储介质中,例如文件系统、HDFS、分布式数据库等。Flink采用异步写入的方式,将状态持久化操作放在后台线程中完成,以避免影响任务的执行性能。在状态恢复时,Flink会从持久化存储中读取最近一次的快照,并将状态恢复到该快照的状态。
  4. 托管方式(Manager State & Raw State)

Flink状态一致性和容错机制

所谓的状态⼀致性,就是计算结果要保证准确,他可以分为以下⼏类:

At-most-once数据最多发送⼀次,有可能会丢失数据

At-least-once数据最少发送⼀次,等待响应,如果⽆应答则继续发送,有可能重复处理数据,从头开始在进⾏⼀次处理,这种场景需要⼈⼯⼲预⾃⼰处理重复数据

Exactly-once每⼀条消息只被流处理系统处理⼀次 End-to-End Exactly-Once端到端的只有⼀次,数据从其他组件读取到Flink,然后写出到其他组件。Flink使⽤了⼀种轻量级快照机制(检查点checkpoint)来保证Exacly-once语义

Flink使⽤了⼀种轻量级快照机制(检查点checkpoint)来保证Exacly-once语义,?在状态⼀致性中也可以通过幂等写⼊和事务写⼊来保证,幂等操作也就是⼀个操作可以重复执⾏很多次,但导致的结果更改只有⼀次,也就是后⾯的重复执⾏不起作⽤,事务写⼊就是应⽤了事务的原⼦性,所有操作要不全部成功,要么⼀个不做。

checkpoint是Flink中的⼀种容错机制,任务失败的时候可以进⾏重启⽽不丢失之前的⼀些信息。它使⽤的是chandy⸺lamport算法,相当于是分布式快照,在特定的时间记录下分布式系统的全局状态(所有进程的状态和Channel的状态),主要⽤于故障恢复,死锁检测,垃圾收集等。

他提供了⼀个数据屏障barrier具体流程如下:当检查点触发的时候,会以检查点ID为数据发送⼀个barrier,这个barrier在传递的过程中都会被⼴播到下游barrier不会进⾏任何的计算,就是为了分割数据,barrier之前是当前检查点数据,barrier之后是下⼀个检查点数据,当算⼦的task接收到barrier说明当前检查点的数据全部被处理完毕,就会保存当前task的状态,发送barrier之后,后续的数据继续传输,整个集群还是⼀个实时计算,我们的Fllink还是只需要保存状态就可以了。并且等到上游所有的并⾏⼦分区barrier都对⻬了,才去保存当前任务的状态。

可以通过配置⽅式:flink-conf.yaml设置restart-strategy对重启进⾏配置
可以通过配置 flink-conf.yaml设置jobmanager.execution.failover-strategy对恢复进⾏配置

Flink批流统一的意义及实现

Flink批流统一(Batch and Stream Processing Unified)是指Flink框架可以同时处理批处理和流式处理任务,将批处理和流式处理的概念统一到同一个计算引擎中。

意义:

批流统⼀允许开发⼈员在处理有界和⽆界数据时使⽤相同的API和逻辑。这减少了学习成本,减轻了维护成本,因为不需要为批处理和流处理分别编写和维护两套代码。

在许多实际情况下,批处理和流处理可能在同⼀个应⽤程序中并存。批流统⼀允许在相同的应⽤程序中执⾏两种处理模式,从⽽更有效地利⽤资源。

有些应⽤程序需要同时处理实时流数据和历史批数据,批流统⼀使这种混合处理更容易。Flink可以根据数据和任务特性⾃动执⾏优化,⽆论数据是有界还是⽆界。批流统⼀使得这些优化更容易实现。

实现:

使⽤DataStream API,允许执⾏各种流处理操作,如map、filter、窗⼝操作、连接、聚合等。对于批处理,可以使用DataStream API的批处理模式。这意味着可以使⽤相同的DataStream API来处理批数据,⽆需切换到不同的API。

DataSet API,虽然DataSet API主要⽤于批数据的处理,但可以使⽤DataSet API的批处理操作在有界数据上执⾏批处理任务。在需要将批处理和流处理结合的情况下,可以将DataSet转换为DataStream或反之,以实现批流统⼀。

Flink的Table API和SQL也⽀持批流统⼀。可以使⽤相同的Table API和SQL查询来处理批数据和流数据,⽆需修改查询。

总结:

  1. 统一编程模型:Flink提供了统一的编程模型,即可以使用相同的API和操作符来编写批处理和流式处理的任务。用户无需学习不同的编程模型,可以更加灵活地切换和组合批处理和流式处理的代码逻辑。
  2. 简化系统架构:传统上,批处理和流式处理往往需要使用不同的系统和工具来处理,需要维护多个独立的作业和环境。而Flink的批流统一可以简化系统架构,只需要维护一个统一的计算引擎,减少了系统的复杂性和维护成本。
  3. 实时处理和增量计算:Flink的批流统一使得流式处理可以实现真正的实时处理和增量计算。通过流式处理的方式,Flink能够实时地处理和分析数据流,并且可以按需进行窗口计算、聚合操作等。同时,Flink也支持将批处理作业转换为增量计算,实现实时感知和响应。
  4. 一致性和容错性:Flink的批流统一保证了批处理和流式处理任务的一致性和容错性。它使用相同的状态管理机制和检查点机制来保证数据一致性和故障恢复,无论是批处理还是流式处理任务都能够达到精确一次的语义。

FlinkCEP复杂事件处理应用

在Flink上层实现的复杂事件处理,也就是让你从⽆限事件流中检测出特定的事件模型,然后掌握数据中重要的部分。处理事件的规则也被叫做模式,每个模式都有⼀个独⼀⽆⼆的名字,使⽤他来识别匹配事件,他⼜可以分为单个模式和组合模式

单个模式:

可以通过匹配次数(times,oneormore)和匹配条件(where/or)进⾏分类

组合模式:

就是将多个单个模式连接在⼀起
可以分为严格连续:匹配上⼀个数据和下⼀个数据必须连在⼀起

松散连续: 两个模式匹配的数据是前后关系即可,不要求紧挨到⼀起

**不确定的松散连续:**放宽条件,之前已经匹配过的事件也可以再次使⽤

FlinkCEP(Complex Event Processing)是Flink框架中的一个库,用于处理和检测符合特定模式的复杂事件序列。以下是一些FlinkCEP在实际应用中的场景

  1. 金融交易风险监测:在金融领域,可以使用FlinkCEP来监测和检测交易数据中的异常事件。例如,可以定义交易异常的规则和模式,如短时间内出现多笔高额交易、连续出现异常操作等。FlinkCEP可以实时地检测这些异常事件,并触发相应的预警或风险控制措施。

  2. 物联网设备监控:在物联网应用中,可以使用FlinkCEP对设备生成的事件流进行实时监视和分析。例如,可以定义设备故障的模式和规则,如连续出现多次的异常温度、湿度超过阈值等。FlinkCEP可以实时地检测这些异常事件,并采取相应的措施,如发送警报、自动触发设备维修等。

  3. 网络安全威胁检测:在网络安全应用中,可以使用FlinkCEP来监测和识别网络攻击和威胁。例如,可以定义恶意行为的模式和规则,如频繁的登录失败、异常的网络流量模式等。FlinkCEP可以实时地检测这些恶意事件,并触发相应的安全控制和反制措施。

  4. 用户行为分析:在电商或在线广告领域,可以使用FlinkCEP来分析用户行为并检测潜在的兴趣和需求。例如,可以定义用户购买行为的模式和规则,如连续购买多个相关商品、频繁访问某一类别的产品等。FlinkCEP可以实时地检测这些用户行为事件,并根据其兴趣和需求进行个性化推荐或广告投放。

这些场景只是FlinkCEP的应用之一,实际上,FlinkCEP还可以用于其他需要处理复杂事件序列的领域和应用中。通过定义事件模式和规则,结合Flink框架提供的流处理和状态管理能力,FlinkCEP能够实时地检测和处理复杂的事件序列,帮助用户实现实时监测、预警和响应。

Flink Watermark机制

⽔位线就是数据流的⼀部分,随着数据传递,⽤于标识时间,⽔位线也可以被看作为是⼀个标记点,时间的标记点,事件时间的标记点,这个需要程序员⾃⼰去处理,时间戳⼀般位于真实数据的后⾯,通过数据本⾝携带的时间戳转换获得(⽔位线是⽤来衡量事件时间)

⽔位线是根据数据产⽣的,这⾥的数据分为有序数据和⽆序数据

有序数据

理想状态下,数据都按照事件时间排序到来,我们⽣成⽔位线的时候,只需要根据事件时间⼀对⼀⽣成即可,⽣成的⽔位线也是有序的,满⾜我们对时间的认知【时间都是从前向后,⽆法逆转】因为数据有序,直接找本间隔内最后⼀条记录⽣成⽔位线即可

⽆序数据

真实场景下,由于设备⽹络等原因或者组件本⾝的特性,导致数据乱序,如果这时按照数据去⽣成⽔位线,会导致不符合我们对时间的认知【时间都是从前向后,⽆法逆转】

所以
1.结合有序数据⽔位线的⽣成,⽔位线需要周期性⽣成[排除1对1⽣成]
2.⽔位线按照本间隔内时间戳最⼤的⼀条去⽣成

总结

Flink中的Watermark机制主要包括以下几个关键点:

  1. 生成Watermark:在Flink的数据源或转换操作中,通过提取事件中的时间戳信息,可以生成对应的Watermark。通常情况下,Watermark的生成策略是基于数据的事件时间戳,并根据具体需求设置一定的延迟。
  2. 发送Watermark:一旦生成Watermark,Flink会在数据流中将其作为特殊的事件进行发送。Watermark随着事件流顺序传递,告知系统该时间戳之前的事件都已经到达。
  3. 触发操作:当Flink接收到Watermark时,会触发与时间有关的操作。例如,在窗口计算中,当Watermark到达窗口的结束时间时,Flink会关闭该窗口并进行相应的计算。
  4. 延迟数据处理:在一些情况下,事件流中的数据可能存在一定的延迟,即晚于Watermark时间戳的事件仍然到达。Flink允许在处理Watermark时设置延迟容忍度,以便对延迟数据进行处理或丢弃。

通过Watermark机制,Flink可以实现基于事件时间的窗口计算、处理乱序数据和解决数据延迟等问题。Watermark为Flink提供了一种有效的方式来处理事件时间,并保证结果的准确性和实时性。同时,用户也可以根据具体需求自定义Watermark生成和处理策略,以便更好地适应各种场景的需求。

Flink窗口函数的应用

Flink窗口函数是一种在时间窗口内对数据进行处理的函数。它将数据流划分成不同的时间窗口,然后对每个窗口中的数据进行计算和统计。Flink提供了多种类型的窗口函数,其中常见的有以下几类:

  1. 滚动窗口函数(Tumbling Window):滚动窗口函数是指固定大小的窗口,它们之间互不重叠,且每个数据元素只属于一个窗口。例如,可以定义一秒钟的滚动窗口,那么每秒钟会处理一次窗口内的数据。
  2. 滑动窗口函数(Sliding Window):滑动窗口函数是指可以重叠的固定大小的窗口。例如,可以定义大小为5秒、滑动步长为1秒的滑动窗口,那么每隔1秒会对5秒的数据进行处理。
  3. 会话窗口函数(Session Window):会话窗口函数是指将不活动的时间段用来定义窗口。例如,可以将30秒不活动作为会话窗口的边界,即如果两个事件间隔时间超过30秒则表示前一个事件所在的会话窗口已经结束。

Flink的窗口函数可以与聚合函数相结合,用于对窗口内的数据进行聚合计算,如求和、平均值等。与窗口函数相结合的聚合函数包括sum、count、min、max、reduce、aggregate等。

除了基本的窗口函数和聚合函数之外,Flink还提供了丰富的窗口API,以实现更加复杂的窗口处理需求。例如,支持在窗口结束前设置触发器(Trigger),以控制数据计算的时机;支持在窗口中进行事件时间(Event Time)和处理时间(Processing Time)的处理等。

Flink窗口函数的应用非常广泛,例如在金融领域可用于对交易数据进行滑动窗口统计,以检测异常交易行为;在物联网领域可用于对设备数据进行会话窗口计算,以识别设备故障和预测维修需求。总之,Flink窗口函数是一种非常有用的数据处理方式,能够帮助用户实现各种复杂的数据计算和分析需求。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值