无限流中的去重计数

3
我正在寻找一种创建流应用程序的方式,它可以承受每秒数百万个事件,并实时输出这些事件的不同计数。由于此流未受任何时间窗口限制,因此显然必须由某些存储支持。然而,我无法找到在保持良好抽象级别的情况下执行此操作的最佳方法(这意味着我希望有一个框架来处理存储和计数,否则我根本不需要框架)。对我而言,首选的存储是Cassandra和Redis(最好两者都有)。
我考虑的选项是Flink、Spark和Kafka Streams。我确实了解它们之间的区别,但仍然无法选择最佳解决方案。能否给些建议?谢谢。

Spark结构化流处理有一些类似用例的示例,请查看https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html。 - Abhishek Choudhary
你能详细说明一下你所说的"实时输出这些事件的不同计数"是什么意思吗?例如,您是否希望在每次唯一计数更改时发出记录(例如在Flink中)?还是在某个定期时间边界上进行呢? - kkrugler
你能分区数据吗,还是这是一个全局唯一计数? - kkrugler
2个回答

3
无论您选择哪种解决方案,如果您可以忍受它不是100%准确(但非常接近),您可以让您的操作员使用HyperLogLog(有可用的Java实现)。这使您实际上不必保留有关每个单独项目的数据,从而大大减少了内存使用量。
假设使用Flink,所需状态非常小(<1MB),因此可以轻松使用基于堆的FSStateBackend,并将检查点写入文件系统,从而减少序列化开销。
同样假设您使用Flink,使用[ContinuousEventTimeTrigger][2],您还可以查看当前正在跟踪多少个唯一项。

我了解HLL,这可能是我要走的路。我只是想知道是否可以使用类似Flink的解决方案来实现这样的功能。我将考虑在HLL运算符中使用它。谢谢。 - Nestor Sokil
啊,很酷,是的,我已经成功地使用了clearspring实现。根据您的需求,您可能需要覆盖序列化,但是我认为Kryo默认生成的序列化应该适用于检查点。如果您使用RocksDB,由于不断的序列化/反序列化,它可能会变得有点慢。 - Joshua DeWald

2
我建议重新考虑存储系统的选择。使用外部系统比使用本地状态慢得多。Flink应用程序在JVM堆或RocksDB(磁盘上)上本地维护状态,并可以将其检查点定期保存到持久存储(如HDFS)中。这个状态可能会变得非常大(10多TB),但仍然可以有效地维护,因为可以增量和异步地进行检查点。这比为每条记录发送查询到外部系统要快得多。
如果您仍然喜欢Redis或Cassandra,则可以使用Flink的AsyncIO运算符发送异步请求以提高应用程序的吞吐量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接