大数据开发:Flink ReScale机制
Flink作为一个热度越来越高的流计算引擎,在越来越多的场景下得到应用,可以说是从寂寂无名到周所周知,其发展态势是整体向上。当然,这也是得益于Flink的高性能和可靠性。今天的大数据开发学习分享,我们来讲讲Flink ReScale机制。
Flink ReScale是什么?
作为流式计算系统,Flink通过快照机制和上游系统(比如kafka)的可回溯性来保证作业状态的一致性。
作业重启从上一次状态恢复,Flink会自动将状态分发到具体的subtask。如果前后并发改变,Flink会将总的状态通过一定策略分发到每个subtask,即所谓的rescale;如果前后并发不变,那么每个subtask对应的状态和之前一样。从这方面来讲,前后并发不变的状态恢复只是rescale中特殊的一种。
作为生产环境的flink,我们期待做到快速failover、弹性扩缩容和平滑迁移,尽量做到用户无感知和变更方便,从而让用户将更多精力放在功能实现上。
Flink Rescale原理
当作业重启时,Flink会重新分配状态。Flink会固定总partition个数,当算子并发改变时,重新计算并将partition分配到每个subtask上。除了这种partition策略,还存在根据partition大小自动合并和拆分的策略,比如Hbase所使用的。
Flink中有两种状态,包括operator state和keyed state。
operator state是以subtask为单位的,一般采用list的形式存储,当重新rescale时每个subtask可以选择接受全部的operator state或者按照list平分。
keyed state是以key为单位的,必须在keyby时候才能使用这种状态。keyed state是最常见的状态类型,keyed state会被划分到多个key group(类似partition)中,之所以选择以key group为基本单位来操作状态,是为了减少磁盘访问IO和随机读写(如果以key为单位就会出现这种情况,比如恢复时每个task都需要读取全部的state来决定每个key是否属于自己)。
下面以kafka offset作为operator state作为介绍。每个subtask都会以list的形式记录自己负责的<partitionId,offset>,当做快照的时候,将状态保存在共享存储,所有subtask的list state会拼接成一个大的list。当重新rescale的时候,flink将list中的元素平分给每个subtask。(实际的flink kafka consumer是通过union方式获取所有list,然后再选择属于自己的)
比方说,Keyed state的rescale,key group的个数等于作业的最大并发(一旦设置不可改变,即key group的个数必须大于等于task的并发度),每个key通过hash映射属于其中一个key group。
当作业rescale的时候,会将list形式的KG平分到每个task。
key->KG→task的映射过程:
计算key的哈希值。
根据哈希值和最大并发确定key所属KG。
根据key所属KG来确定发到下游哪个并发的task。
对应KeyGroupRangeAssignment代码如下:
public static int assignKeyToParallelOperator(Object key,int maxParallelism,int parallelism){
Preconditions.checkNotNull(key,"Assigned key must not be null!");
return computeOperatorIndexForKeyGroup(maxParallelism,parallelism,assignToKeyGroup(key,maxParallelism));
}
public static int assignToKeyGroup(Object key,int maxParallelism){
Preconditions.checkNotNull(key,"Assigned key must not be null!");
return computeKeyGroupForKeyHash(key.hashCode(),maxParallelism);
}
public static int computeOperatorIndexForKeyGroup(int maxParallelism,int parallelism,int keyGroupId){
return keyGroupId*parallelism/maxParallelism;
}
上游的计算在KeyGroupStreamPartitioner类里,下游的计算在KeyGroupPartitioner类里。
关于大数据开发,Flink ReScale机制,以上就为大家做了简单的介绍了。在流式计算领域,Flink的战斗力可以说是得到普遍认可的,Flink框架也值得深入细致地学习。