В контексте данного конкретного учебного упражнения для каждого значения rideId есть три события: начальное событие TaxiRide, конечное событие TaxiRide и TaxiFare. Цель этого упражнения - связать каждое стартовое событие TaxiRide с одним событием TaxiFare, имеющим один и тот же поездку, или другими словами, присоединиться к потоку поездки и потоку тарифа на поездке, зная, что будет только одно из них.
Это упражнение демонстрирует, как работает ключевое состояние в Flink. Keyed state - это хранилище значений ключей. Когда у нас есть элемент ValueState
, такой как ValueState<TaxiRide> rideState
, Flink будет хранить отдельную запись в своем бэкэнде состояния для каждого отдельного значения ключа (rideId
).
Каждый раз, когда flatMap1
и flatMap2
вызываются, есть неявно ключ (a rideId
) в контексте, и когда мы вызываем rideState.update(ride)
или rideState.value()
, мы обращаемся не к одной переменной, а к установке и получение записи в хранилище значений ключей, используя rideId
в качестве ключа.
В этом упражнении оба потока обозначаются rideId
, поэтому потенциально существует один элемент rideState
и один элемент fareState
для каждого отдельного rideId
. Следовательно, решение, которое было предоставлено, заключается в буферизации множества поездок и тарифов, но только по одной для каждого rideId
(этого достаточно, учитывая, что поездки и тарифы идеально согласованы в этом наборе данных).
Итак, вы спросили:
Как функция EnrichmentFunction способна объединить два потока, иначе. как он узнает, к какому тарифу присоединиться, к какой поездке?
И ответ
Он присоединяется к тарифу с тем же rideId
.
В этом конкретном упражнении, о котором вы спрашивали, показано, как реализовать простое объединение с обогащением для представления идей состояния ключа и связанных потоков. Но более сложные объединения, безусловно, возможны с Flink. См. документы по объединению , объединения с таблицей Flink API , объединения с Flink SQL и упражнение по объединениям на основе времени для получения дополнительной информации.