Apache Flink - реализация потокового процессора с потенциально очень большим состоянием

Я хочу спроецировать потенциально очень большое состояние из потока событий. Вот как я могу реализовать это в обязательном порядке:

class ImperativeFooProcessor {

  val state: mutable.Map[UUID, BarState] = mutable.HashMap.empty[UUID, BarState]

  def handle(event: InputEvent) = {
    event match {
      case FooAdded(fooId, barId) => {
        // retrieve relevant state and do some work on it
        val barState = state(barId)

        // let the world know about what may have happened
        publish(BarOccured(fooId, barId))
        // or maybe rather
        publish(BazOccured(fooId, barId))
      }
      case FooRemoved(fooId, barId) => {
        // retrieve relevant state and do some work on it
        val barState = state(barId)

        // let the world know about what may have happened
        publish(BarOccured(fooId, barId))
        // or maybe rather
        publish(BazOccured(fooId, barId))
      }
    }
  }

  private def publish(event: OutputEvent): Unit = {
    // push event to downstream sink
  }
}

В худшем случае размер BarState будет увеличиваться в зависимости от того, сколько раз он был упомянут FooAdded.

Количество уникальных barId очень мало по сравнению с общим количеством событий для каждого barId.

Как мне начать представлять эту структуру обработки во Flink?

Как мне работать с тем фактом, что каждое состояние BarState потенциально может стать очень большим?


person Ploo    schedule 28.03.2017    source источник


Ответы (1)


Flink поддерживает состояние в так называемых серверах состояния. Существуют серверные программы состояния (MemoryStateBackend и FsStateBackend), которые работают в куче JVM рабочих процессов. Эти серверные модули не подходят для обработки большого состояния.

Flink также имеет RocksDBStateBackend, основанный на RocksDB. RocksDB используется как локальная база данных (нет необходимости настраивать ее как внешнюю службу) на каждом рабочем узле и записывает данные о состоянии на диск. Следовательно, он может обрабатывать очень большие состояния, превышающие объем памяти.

Flink предлагает KeyedStream, который представляет собой поток, разделенный по определенному атрибуту. В вашем случае вы, вероятно, хотите, чтобы весь доступ к одному и тому же идентификатору передавался в один и тот же экземпляр состояния, поэтому вы должны использовать barId в качестве ключа. Затем состояние распределяется по всем параллельным рабочим потокам на основе barId. По сути, это распределенное хранилище или карта значений ключей. Таким образом, вам не нужно представлять состояние в виде карты, потому что оно автоматически распространяется Flink.

person Fabian Hueske    schedule 29.03.2017