Flink如何清理键控状态?

问题描述 投票:0回答:1

当考虑到通过某些东西进行键控的行为时,我传统上想到的比喻是把所有符合键控的事件扔进同一个桶里。正如你可以想象的那样,当Flink应用开始处理大量数据时,你所选择的键值开始变得很重要,因为你要确保你能很好地清理状态。这就引出了我的问题,Flink到底是如何清理这些 "桶 "的?如果bucket是空的(所有的MapStates和ValueStates都是空的),Flink是否会关闭键空间的那个区域,并删除bucket?

举例来说,如果是这样的话,Flink是否会关闭该区域的键空间并删除该桶?

传入数据格式: {userId, computerId, amountOfTimeLoggedOn}。

键。 UserIdComputerId

当前键空间。

  • 爱丽丝,10号电脑,有两个事件。两个事件都存储在状态中。
  • 鲍勃,电脑11:没有事件。没有任何东西被存储在状态中。

Flink最终会从Key Space中删除Bob, Computer 11,还是因为它曾经有一个事件在里面而永远存在?

apache-flink flink-streaming
1个回答
1
投票

Flink不会为没有任何用户值相关联的状态键存储任何数据,至少在现有的状态后端。Heap(内存中)或RocksDB。

Key Space在Flink中是虚拟的,Flink不对哪些具体的键可能存在做任何假设。每个键或键的子集没有任何预分配的桶。只有当用户应用为某个键写入一些值后,它才会占用存储空间。

一般的想法是,所有具有相同键的记录都在同一台机器上处理(有点像你说的在同一个桶里)。某个键的本地状态也总是保存在同一台机器上(如果有存储的话)。不过这和检查点没有关系。

对于你的例子,如果在某个时间点为[Bob,Computer 11]写入了某个值,随后又被删除,Flink就会把它和key一起彻底删除。


0
投票

简答

在Time To Live的帮助下,它清理了。(TTL) Flink状态和Java Garbage Collector的功能。(GC). TTL功能将删除对状态条目的任何引用,GC将收回分配的内存。

长应答

你的问题可以分为3个小问题。

我会尽量简短地回答你的问题。

Flink如何基于Key对数据进行分区?

对于一个操作者在键流上的操作,Flink在键的帮助下对数据进行分区。一致的哈希算法. 它创造了 max_parallelism 桶的数量。每个操作者实例都被分配到一个或多个这样的数据桶。每当一个数据点被发送到下游时,键被分配到这些数据桶中的一个,并因此被发送到相关的操作者实例。这里没有存储键,因为范围是以数学方式计算的。因此,任何时候都不会清除区域或删除数据斗。. 你可以创建任何类型的键。它不会影响键空间或范围的内存。

Flink如何用key存储状态?

所有的操作符实例都有一个实例级的状态存储。这个存储定义了该运算符实例的状态上下文,它可以存储多个命名状态存储,例如 "count"、"sum"、"ome-name "等。这些命名-状态存储是Key-Value存储,可以根据数据的key存储值。

这些KV存储是在我们用状态描述符初始化状态时创建的,在 open() 的函数,即 getRuntimeContext().getValueState().

这些KV存储只有在需要在状态中存储一些东西的时候才会存储数据。(如 HashMap.put(k,v)). 因此,没有键或值被存储,除非状态更新方法(如 update, add, put)被称为。

所以。

  • 如果Flink没有看到一个键,则不会为该键存储任何东西。
  • 如果Flink已经看到了键,但没有调用状态更新方法,则不会为该键存储任何东西。
  • 如果对一个键调用了状态更新方法,那么键值对将被存储在KV存储中。

Flink如何清理key的状态?

Flink不会删除状态,除非用户需要或者用户手动完成。如前所述,Flink对状态有TTL功能。这个TTL会标记状态的到期时间,并在调用清理策略时将其删除。这些清理策略因后端类型和清理时间的不同而不同。对于堆状态后端,它将从状态表中删除条目,即删除对该条目的任何引用。这个非引用条目占用的内存将被Java GC清理。对于RocksDB状态后端,它只需调用本地的 delete RocksDB的方法。

© www.soinside.com 2019 - 2024. All rights reserved.