У меня, я считаю, относительно распространенный прецедент для искрового потока:
У меня есть поток объектов, которые я хотел бы фильтровать на основе некоторых справочных данных
Вначале я думал, что это будет очень простая задача для достижения использования широковещательной переменной:
public void startSparkEngine {
Broadcast<ReferenceData> refdataBroadcast
= sparkContext.broadcast(getRefData());
final JavaDStream<MyObject> filteredStream = objectStream.filter(obj -> {
final ReferenceData refData = refdataBroadcast.getValue();
return obj.getField().equals(refData.getField());
}
filteredStream.foreachRDD(rdd -> {
rdd.foreach(obj -> {
// Final processing of filtered objects
});
return null;
});
}
Однако, хотя редко, мои справочные данные будут периодически меняться
У меня создалось впечатление, что я могу модифицировать и повторно транслировать мою переменную на драйвер, и она будет распространена среди каждого из рабочих, однако объект Broadcast
не Serializable
и должен быть final
.
Какие у меня альтернативы? Три решения, о которых я могу думать, следующие:
-
Переместите поиск ссылочных данных в
forEachPartition
илиforEachRdd
, чтобы он полностью находился на рабочих. Однако ссылочные данные живут в REST API, поэтому мне также нужно каким-то образом хранить таймер/счетчик, чтобы остановить доступ к удаленному доступу для каждого элемента в потоке. -
Перезапустите контекст Spark каждый раз при обновлении refdata с новой переменной Broadcast.
-
Преобразуйте ссылочные данные в RDD, а затем
join
потоки таким образом, чтобы теперь я потоковалPair<MyObject, RefData>
, хотя это будет отправлять опорные данные каждому объекту.