我们正在考虑使用flink重建我们的一个系统,并试图考虑一些情况。作为一个简单的例子,让我们假设我们有实体和实体活动。每当一个活动事件进来时,它只有一个实体id,我们希望在将其传递给更多处理之前将活动与实体连接起来。可能的实体数量非常大(,关于用户的元数据不会经常改变,但可以改变。
我们认为有几种方法可以解决这个问题,第一种是加入流(用户更新流和活动流),但由于用户的最后一次更新可能是很久以前(可能是几年前),我们不能真正使用这种方法。
另一种方法是使用有状态操作,将用户元数据存储在其状态中。当一个Activity进入时,我们可以在状态中查找用户并附加元数据。这样做的问题是,在我们的情况下,用户元数据状态可能会非常大(数十亿)。将所有实体始终保存在状态存储中似乎不太理想,尽管也许是最好的方法?
另一种方法是将我们的状态存储在数据库中并对其进行查询,但是我们要么只需要查询主数据库以确保我们拥有最新的数据,要么查询辅助数据库,并且必须担心复制延迟和可能错过更新。
我能想到的最后一种方法是做一个混合体,我们使用一个有状态的存储和一个ttl来防止它变得太大,同时也将对存储所做的任何更新推送到一个db。我们总是尝试首先从状态中拉取,如果它不存在,我们就回退到DB。这意味着任何时候实体被更新,它都将在存储中用于TTL(保证我们有最新的数据)。我们还可以在任何时候将数据推到存储中,我们必须回退到数据库(如果一个实体做了一些事情,他们可能会做更多的事情,所以将他们的信息保持在状态中)。
我对这两种使用数据库的方法的主要关注点都与检查点有关。如果Flink需要为它的状态恢复检查点,我不明白数据库如何也能轻松地考虑到这一点。它将在'head'处具有状态,而有状态函数将在检查点处具有状态。假设我们的代码中有一个错误,需要恢复一个检查点/这可能是有状态函数和数据库之间的一个很大的区别。
我想知道处理这类案件是否有共同的模式
1条答案
按热度按时间bybem2ql1#
您已经概述了4种方法:
(1)加入用户数据和用户活动流
(2)以 Flink 状态存储用户数据
(3)从外部数据库查找用户数据
(4)混合,使用Flink状态作为缓存
我看不出(1)和(2)之间有任何真实的区别。Flink SQL时态连接的行为与描述的一样,听起来应该是易于处理的。
(3)听起来像是Flink SQL查找连接。
至于缓存,Flink SQL查找连接可以使用缓存,但你可能不关心它的语义。该高速缓存在内存中,而不是在Flink状态。缓存的数据只要存在就被使用。该高速缓存有TTL,但当底层DB更新时,不会更新该高速缓存。