学习 Flink(十七):HyperLogLog 去重计数

 

在需要对数据进行去重计数的场景里,实现方式是将数据明细存储在集合的数据结构中。然而,随着数据随时间的不断累积,明细数据占用了大量的存储空间。使用 HyperLoglog 去重计数,在牺牲非常小准确性的情况下,可以极大的减少数据存储。

依赖

编辑 pom.xml 文件,添加依赖:

<dependency>  
    <groupId>net.agkn</groupId>
    <artifactId>hll</artifactId>
    <version>1.6.0</version>
</dependency>  

使用

定义状态:

private ValueState<Byte[]> hllState;  

初识化状态:

@Override
public void open(Configuration parameters) throws Exception {  
    super.open(parameters);
    ValueStateDescriptor<Byte[]> hllStateDescriptor = new ValueStateDescriptor<>(
        "hll",
        Types.OBJECT_ARRAY(Types.BYTE)
    );

    this.hllState = getRuntimeContext().getState(hllStateDescriptor);
}

处理方法中,由状态获取 HLL:

HLL hll = null;  
if (this.hllState.value() == null) {  
    hll = new HLL(14, 5);
} else {
    hll = HLL.fromBytes(ArrayUtils.toPrimitive(this.hllState.value()));
}

处理方法中,由 HLL 更新状态:

this.hllState.update(ArrayUtils.toObject(hll.toBytes()));  
Flink可以通过使用SetState来实现历史全量去重计数。具体实现步骤如下: 1.定义一个MapState作为状态,用于存储历史据的去重结果。 ``` MapState<String, Long> countState = getRuntimeContext().getMapState(new MapStateDescriptor<>("countState", String.class, Long.class)); ``` 2.在KeyedProcessFunction的processElement方法中,判断当前据是否已经存在于状态中,如果不存在则将其加入状态,并将计数器加1。 ``` @Override public void processElement(T value, Context ctx, Collector<Long> out) throws Exception { //获取当前事件的key和value String key = ctx.getCurrentKey(); Long currentValue = value.get(); //如果当前事件不存在于状态中,就将其加入状态并将计数器加1 if (!countState.contains(currentValue.toString())) { countState.put(currentValue.toString(), 1L); out.collect(countState.values().iterator().next()); } } ``` 3.在Job中设置状态后端,并启动Job。 ``` StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setStateBackend(new RocksDBStateBackend("hdfs://localhost:9000/flink/checkpoints")); DataStream<Tuple2<String, Long>> input = env.fromElements( Tuple2.of("key", 1L), Tuple2.of("key", 1L), Tuple2.of("key", 2L), Tuple2.of("key", 3L), Tuple2.of("key", 2L), Tuple2.of("key", 4L), Tuple2.of("key", 5L), Tuple2.of("key", 3L) ); input.keyBy(0) .process(new CountDistinct()) .print(); env.execute(); ``` 这样就可以实现历史全量去重计数了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值