Sistema de ventanas

El SDK de Dataflow usa un concepto llamado sistema de ventanas para subdividir una PCollection de acuerdo con las marcas de tiempo de sus elementos individuales. Las transformaciones de Dataflow que agregan múltiples elementos, como GroupByKey y Combine, funcionan de forma implícita por ventana, es decir, procesan cada PCollection como una sucesión de ventanas múltiples y finitas, aunque toda la colección en sí puede ser de tamaño ilimitado o infinito.

Los SDK de Dataflow usan un concepto relacionado llamado Activadores a fin de determinar cuándo “cerrar” cada ventana finita a medida que llegan datos no delimitados. El uso de un activador puede ayudar a definir mejor la estrategia de ventanas para tu PCollection a fin de tratar con los datos que llegan tarde o para proporcionar resultados tempranos. Para obtener más información, consulta Activadores.

Conceptos básicos del sistema de ventanas

El sistema de ventanas es más útil con una PCollection no delimitada, que representa un conjunto de datos en constante actualización de tamaño desconocido/ilimitado (p. ej., datos de transmisión). Algunas transformaciones de Dataflow, como GroupByKey y Combine, agrupan varios elementos con una clave común. En general, esa operación de agrupación agrupa todos los elementos que tienen la misma clave en todo el conjunto de datos. Con un conjunto de datos de delimitados, es imposible recopilar todos los elementos, ya que se agregan nuevos elementos de forma constante.

En el modelo de Dataflow, cualquier PCollection puede subdividirse en ventanas lógicas. Cada elemento de PCollection se asigna a una o más ventanas de acuerdo con la función analítica de PCollection, y cada ventana individual contiene un número finito de elementos. Luego, las transformaciones de agrupación consideran cada elemento de PCollection por ventana. GroupByKey, por ejemplo, agrupa de forma implícita los elementos de una PCollection por clave y ventana. Dataflow solo agrupa los datos dentro de la misma ventana y no agrupa los datos en otras ventanas.

Restricciones del sistema de ventanas

Una vez que configuras la función analítica para PCollection, las ventanas de elementos se usan la próxima vez que apliques una transformación de agrupación a esa PCollection. Dataflow realiza la agrupación real de ventanas según sea necesario; si configuras una función analítica con la transformación Window, cada elemento se asigna a una ventana, pero las ventanas no se consideran hasta que agrupas la PCollection con GroupByKey o Combine. Esto puede tener diferentes efectos en tu canalización.

Considera el ejemplo de canalización en la Figura 1 a continuación:

Una canalización que aplica un sistema de ventanas, un ParDo y un GroupByKey en orden
Figura 1: Canalización con la aplicación de un sistema de ventanas

En la canalización anterior, creamos una PCollection no delimitada mediante la lectura de un conjunto de pares clave-valor con PubsubIO y, luego, aplicamos una función analítica con la transformación Window. Luego, aplicamos un ParDo a la colección y agrupamos el resultado de ese ParDo con GroupByKey. La función analítica no tiene efecto sobre la transformación de ParDo porque, en realidad, las ventanas no se usan hasta que se necesitan para el GroupByKey.

Sin embargo, las transformaciones posteriores se aplican al resultado del GroupByKey, es decir, los datos agrupados por clave y ventana.

Usa el sistema de ventanas con PCollections delimitadas

Puedes usar un sistema de ventanas con conjuntos de datos de tamaño fijo en PCollections delimitadas. Sin embargo, ten en cuenta que los sistemas de ventanas solo consideran las marcas de tiempo implícitas asociadas a cada elemento de una PCollection, y las fuentes de datos que crean conjuntos de datos fijos (como TextIO y BigQueryIO) asignan la misma marca de tiempo a cada elemento. Esto significa que todos los elementos son, de forma predeterminada, parte de una única ventana global. Tener todos los elementos asignados a la misma ventana hará que una canalización se ejecute en el clásico estilo de lote de MapReduce.

Para usar un sistema de ventanas con conjuntos de datos fijos, puedes asignar tus propias marcas de tiempo a cada elemento. Para asignar marcas de tiempo a elementos, usas una transformación de ParDo con un DoFn que genera cada elemento con una marca de tiempo nueva.

El uso de un sistema de ventanas con una PCollection delimitada puede afectar la forma en que tu canalización procesa datos. Por ejemplo, considera la siguiente canalización:

Una canalización que aplica un GroupByKey seguido de un ParDo en una colección delimitada
Figura 2: GroupByKey y ParDo sin sistema de ventanas, en una colección delimitada.

En la canalización anterior, creamos una PCollection delimitada mediante la lectura de un conjunto de pares clave-valor con TextIO. Luego, agrupamos la colección mediante GroupByKey y aplicamos una transformación de ParDo a la PCollection agrupada. En este ejemplo, el GroupByKey crea una colección de claves únicas y, luego, se aplica el ParDo exactamente una vez por clave.

Ahora, considera la misma canalización, pero mediante una función analítica:

Una canalización que aplica un sistema de ventanas, luego un GroupByKey seguido de un ParDo en una colección delimitada
Figura 3: GroupByKey y ParDo con sistema de ventanas, en una colección delimitada.

Como antes, la canalización crea una PCollection delimitada de pares clave-valor. Entonces, establecemos una función analítica para esa PCollection. Ahora, la transformación GroupByKey agrupa los elementos de la PCollection por clave y por ventana. Se aplica la siguiente transformación ParDo varias veces por clave, una vez por cada ventana.

Funciones analíticas

Los SDK de Dataflow te permiten definir diferentes tipos de ventanas para dividir los elementos de tu PCollection. El SDK proporciona, entre otras, las siguientes funciones analíticas:

  • Períodos de tiempo fijos
  • Períodos de tiempo variables
  • Ventanas por sesión
  • Ventana global única

Ten en cuenta que cada elemento puede pertenecer lógicamente a más de una ventana, según la función analítica que uses. El sistema de ventanas de tiempo variable, por ejemplo, crea ventanas superpuestas en las que se puede asignar un solo elemento a varias ventanas.

Períodos de tiempo fijos

La forma más simple de un sistema de ventanas es un período de tiempo fijo: dada una PCollection con marca de tiempo, que podría actualizarse de forma continua, cada ventana podría capturar (por ejemplo) cinco minutos de elementos.

Un período de tiempo fijo representa el intervalo de tiempo en la transmisión de datos que define un paquete de datos para su procesamiento. Considera una ventana que funciona a intervalos de cinco minutos: todos los elementos de tu PCollection no delimitada con valores de marca de tiempo entre 0:00:00 y 0:04:59 pertenecen a la primera ventana, elementos con valores de marca de tiempo entre 0:05:00 y 0:09:59 pertenecen a la segunda ventana, y así sucesivamente.

Un diagrama que representa un sistema de ventanas de tiempo fijo
Figura 4: Períodos de tiempo fijos con duración de 30 s.

Períodos de tiempo variables

Un período de tiempo variable también usa intervalos de tiempo en la transmisión de datos para definir paquetes de datos; sin embargo, con los sistemas de ventanas de tiempo variable, las ventanas se superponen. Cada ventana puede capturar cinco minutos de datos, pero una nueva ventana comienza cada diez segundos. La frecuencia con la que comienzan las ventanas deslizantes se denomina período. Por lo tanto, nuestro ejemplo tendría un tamaño de ventana de cinco minutos y un período de diez segundos.

Debido a que varias ventanas se superponen, la mayoría de los elementos en un conjunto de datos pertenecerán a más de una ventana. Este tipo de sistema de ventanas es útil para tomar promedios de datos en ejecución; cuando usas períodos de tiempo variables, puedes calcular un promedio de ejecución de los datos de los últimos cinco minutos, actualizados cada diez segundos, en nuestro ejemplo.

Un diagrama que representa un sistema de ventanas de tiempo deslizante
Figura 5: Períodos de tiempo variables, con duraciones de 1 minuto y 30 segundos.

Ventanas de sesión

Una función de ventana de sesión define ventanas alrededor de áreas de concentración en los datos. El sistema de ventanas de sesión es útil para los datos que no se distribuyen con regularidad con respecto al tiempo; por ejemplo, una transmisión de datos que representa la actividad del mouse del usuario puede tener largos períodos de tiempo de inactividad intercalados con altas concentraciones de clics. Los sistemas de ventanas de sesión agrupan las concentraciones de datos altas en ventanas separadas y filtran las secciones inactivas de la transmisión de datos.

Ten en cuenta que los sistemas de ventanas de sesión se aplican por clave; es decir, agrupar en sesiones solo toma en cuenta los datos que tienen la misma clave. Por lo tanto, cada clave en tu recopilación de datos se agrupará en ventanas separadas de diferentes tamaños.

El tipo de sistema de ventanas de sesión más simple especifica una duración mínima de intervalo. Todos los datos que llegan por debajo de un umbral mínimo de retraso de tiempo se agrupan en la misma ventana. Si los datos llegan después del tiempo mínimo de tiempo de intervalo especificado, esto inicia el comienzo de una nueva ventana.

Un diagrama que representa un sistema de ventanas de sesión
Figura 5: Ventanas de sesión, con una duración mínima de intervalo. Observa cómo cada clave de datos tiene diferentes ventanas, según su distribución de datos.

Ventana global única

De forma predeterminada, todos los datos de una PCollection se asignan a una única ventana global. Si tu conjunto de datos es de un tamaño fijo, puedes dejar la ventana global predeterminada para tu PCollection. Si los elementos de tu PCollection pertenecen a una única ventana global, tu canalización se ejecutará de manera muy similar a un trabajo de procesamiento por lotes (como en el procesamiento basado en MapReduce).

Otras funciones analíticas

Los SDK de Dataflow proporcionan más funciones analíticas además de las ventanas fijas, variables, de sesión y globales, como ventanas basadas en el calendario.

Java

Consulta el paquete com.google.cloud.dataflow.sdk.transforms.windowing si quieres obtener una lista completa de las funciones analíticas en el SDK de Dataflow para Java.

Configura la función analítica de tu PCollection

Puedes configurar la función analítica para una PCollection si aplicas la transformación Window. Cuando aplicas la transformación Window, debes proporcionar una WindowFn. La WindowFn determina la función analítica que tu PCollection usará para las siguientes transformaciones de agrupación, como un período de tiempo fijo o deslizante.

Los SDK de Dataflow proporcionan WindownFns predefinidas para las funciones analíticas básicas o puedes definir tu propia WindowFn en casos avanzados.

Técnicamente, como todas las transformaciones, Window toma una PCollection de entrada y da como resultado una PCollection nueva con cada elemento asignado a una o más ventanas lógicas y finitas.

Configura períodos de tiempo fijos

El siguiente código de ejemplo muestra cómo aplicar la Window para dividir una PCollection en ventanas fijas, cada una de un minuto de duración:

Java

  PCollection<String> items = ...;
  PCollection<String> fixed_windowed_items = items.apply(
    Window.<String>into(FixedWindows.of(Duration.standardMinutes(1))));

Configura períodos de tiempo variables

El siguiente código de ejemplo muestra cómo aplicar la Window para dividir una PCollection en períodos de tiempo variables. Cada ventana tiene una duración de 30 minutos y una nueva ventana comienza cada cinco segundos:

Java

  PCollection<String> items = ...;
  PCollection<String> sliding_windowed_items = items.apply(
    Window.<String>into(SlidingWindows.of(Duration.standardMinutes(30)).every(Duration.standardSeconds(5))));

Configura ventanas de sesión

El siguiente código de ejemplo muestra cómo aplicar Window para dividir una PCollection en ventanas de sesión, en la que cada sesión debe estar separada por un intervalo de tiempo de 10 minutos como mínimo:

Java

  PCollection<String> items = ...;
  PCollection<String> session_windowed_items = items.apply(
    Window.<String>into(Sessions.withGapDuration(Duration.standardMinutes(10))));

Ten en cuenta que las sesiones son por clave: cada clave en la colección tendrá sus propios grupos de sesiones según la distribución de la fecha.

Configura una única ventana global

Si tu PCollection está delimitada (el tamaño es fijo), puedes asignar todos los elementos a una única ventana global. El siguiente código de ejemplo muestra cómo configurar una única ventana global para una PCollection:

A fin de establecer una única ventana global para tu PCollection, pasa new GlobalWindows() como la WindowFn cuando apliques la transformación Window. El siguiente código de ejemplo muestra cómo aplicar Window para asignar PCollection en una única ventana global:

Java

  PCollection<String> items = ...;
  PCollection<String> batch_items = items.apply(
    Window.<String>into(new GlobalWindows()));

Sesgo de tiempo, retraso de datos y datos tardíos

En cualquier sistema de procesamiento de datos, hay una cierta cantidad de retraso entre el momento en que ocurre un evento de datos (el “tiempo de evento”, determinado por la marca de tiempo en el elemento de datos en sí) y el tiempo en que el elemento de datos real se procesa en cualquier etapa en tu canalización (el “tiempo de procesamiento”, determinado por el reloj en el sistema que procesa el elemento).

En un sistema perfecto, el tiempo de evento para cada elemento de datos y el tiempo de procesamiento serían iguales, o al menos tendrían un delta coherente. Sin embargo, en cualquier sistema de computación del mundo real, la generación y entrega de datos están sujetas a cualquier número de limitaciones temporales. En sistemas grandes o distribuidos, como una colección distribuida de frontend web que genera pedidos de clientes o archivos de registro, no hay garantías de que los eventos de datos aparezcan en tu canalización en el mismo orden en que se generaron en varios lugares de la Web.

Por ejemplo, digamos que tenemos una PCollection que usa un sistema de ventanas de tiempo fijo, con ventanas de cinco minutos de duración. Para cada ventana, Dataflow debe recopilar todos los datos con una marca de tiempo de tiempo de evento en el rango de ventana dado (0:00 y 4:59 en la primera ventana, por ejemplo). Los datos con marcas de tiempo fuera de ese rango (datos de 5:00 o posteriores) pertenecen a una ventana diferente.

Sin embargo, no siempre se garantiza que los datos lleguen a una canalización en el orden correcto de tiempo o que siempre lleguen a intervalos predecibles. Dataflow rastrea una marca de agua, que es la noción del sistema de cuándo se puede esperar que todos los datos en una ventana determinada hayan llegado a la canalización. Los datos que llegan con una marca de tiempo después de la marca de agua se consideran datos tardíos.

De nuestro ejemplo, supongamos que tenemos una marca de agua simple que supone unos 30 segundos de tiempo de retraso entre las marcas de tiempo de los datos (el tiempo del evento) y la hora en que los datos aparecen en la canalización (el tiempo de procesamiento), entonces el flujo de datos cerraría la primera ventana en 5:30. Si un registro de datos llega a las 5:34, pero con una marca de tiempo que lo pondría en la ventana de 0:00 a 4:59 (por ejemplo, 3:38), ese registro es de datos tardíos.

Nota: Para simplificar, suponemos que usamos una marca de agua muy directa que calcula el tiempo de retardo/sesgo de tiempo. En la práctica, tu fuente de datos de PCollection determina la marca de agua y estas pueden ser más precisas o complejas.

Administra el sesgo de tiempo y los datos tardíos

Puedes permitir datos tardíos mediante la invocación de la operación .withAllowedLateness cuando configuras tu estrategia de sistema de ventanas de PCollection. El siguiente ejemplo de código muestra una estrategia de sistema de ventanas que permitirá datos tardíos hasta dos días después del final de una ventana.

Java

  PCollection<String> items = ...;
  PCollection<String> fixed_windowed_items = items.apply(
    Window.<String>into(FixedWindows.of(Duration.standardMinutes(1)))
          .withAllowedLateness(Duration.standardDays(2)));

Cuando estableces .withAllowedLateness en una PCollection, ese retraso permitido se propaga a cualquier PCollection subsiguiente derivada desde la primera PCollection a la que aplicaste el retraso. Si deseas cambiar el retraso permitido más adelante en tu canalización, debes hacerlo de forma explícita de nuevo con Window.withAllowedLateness().

También puedes usar la API de Activadores de Dataflow a fin de ayudarte a definir mejor la estrategia del sistema de ventanas para una PCollection. Puedes usar los activadores para determinar con exactitud cuándo se agrega cada ventana individual y cuándo informa sus resultados, lo que incluye cómo la ventana emite elementos tardíos.

Nota: Las estrategias predeterminadas de sistema de ventanas y activadores de Dataflow descartan los datos tardíos. Si deseas asegurarte de que tu canalización maneje instancias de datos tardíos, deberás establecer .withAllowedLateness de forma explícita cuando configures tu estrategia de sistema de ventanas de PCollection y configurar activadores para tus PCollections en consecuencia.

Agrega marcas de tiempo a los elementos de una PCollection

Puedes asignar nuevas marcas de tiempo a los elementos de una PCollection mediante una transformación de ParDo que genere elementos nuevos con marcas de tiempo que establezcas. Asignar marcas de tiempo puede ser útil si deseas usar las características del sistema de ventanas de Dataflow, pero tu conjunto de datos proviene de una fuente sin marcas de tiempo implícitas (como un archivo de TextIO).

Este es un buen patrón a seguir cuando tu conjunto de datos incluye marcas de tiempo, pero la fuente de datos de Dataflow no las genera. Un ejemplo podría ser un caso en que tu canalización lea registros de un archivo de entrada y cada registro de registro incluya un campo de marca de tiempo; dado que tu canalización lee los registros desde un archivo, la fuente del archivo no asigna marcas de tiempo de forma automática. Puedes analizar el campo de marca de tiempo desde cada registro y usar una transformación de ParDo para adjuntar las marcas de tiempo a cada elemento en tu PCollection.

Java

Para asignar marcas de tiempo, tu transformación de ParDo necesita usar un DoFn que genere elementos con ProcessContext.outputWithTimestamp (en lugar de la ProcessContext.output habitual usada para emitir elementos a la colección de salida principal). El siguiente código de ejemplo muestra un ParDo con un DoFn que genera elementos con nuevas marcas de tiempo:

  PCollection<LogEntry> unstampedLogs = ...;
  PCollection<LogEntry> stampedLogs =
      unstampedLogs.apply(ParDo.of(new DoFn<LogEntry, LogEntry>() {
        public void processElement(ProcessContext c) {
          // Extract the timestamp from log entry we're currently processing.
          Instant logTimeStamp = extractTimeStampFromLogEntry(c.element());
          // Use outputWithTimestamp to emit the log entry with timestamp attached.
          c.outputWithTimestamp(c.element(), logTimeStamp);
        }
      }));
¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Si necesitas ayuda, visita nuestra página de asistencia.