¿Cuándo son realmente confiables los acumuladores?
Quiero usar un acumulador para recopilar algunas estadísticas sobre los datos que estoy manipulando en un trabajo de Spark. Idealmente, lo haría mientras el trabajo calcula las transformaciones requeridas, pero dado que Spark volvería a calcular las tareas en diferentes casos, los acumuladores no reflejarían métricas verdaderas. Así es como la documentación describe esto:
Para las actualizaciones del acumulador realizadas solo dentro de las acciones, Spark garantiza que la actualización de cada tarea al acumulador solo se aplicará una vez, es decir, las tareas reiniciadas no actualizarán el valor. En las transformaciones, los usuarios deben tener en cuenta que la actualización de cada tarea se puede aplicar más de una vez si las tareas o las etapas del trabajo se vuelven a ejecutar.
Esto es confuso ya que la mayoríacomportamiento no permiten ejecutar código personalizado (donde se pueden usar acumuladores), en su mayoría toman los resultados de transformaciones anteriores (perezosamente). La documentación también muestra esto:
val acc = sc.accumulator(0)
data.map(x => acc += x; f(x))
// Here, acc is still 0 because no actions have cause the `map` to be computed.
Pero si agregamosdata.count()
al final, ¿se garantizaría que esto sea correcto (no tiene duplicados) o no? Claramenteacc
no se usa "solo dentro de acciones", ya que el mapa es una transformación. Por lo tanto, no debe garantizarse.
Por otro lado, la discusión sobre los tickets relacionados con Jira habla sobre "tareas de resultados" en lugar de "acciones". Por ejemploaquí yaquí. Esto parece indicar que se garantizaría que el resultado sea correcto, ya que estamos utilizandoacc
inmediatamente antes y acción y, por lo tanto, debe calcularse como una sola etapa.
Supongo que este concepto de "tarea de resultado" tiene que ver con el tipo de operaciones involucradas, siendo la última que incluye una acción, como en este ejemplo, que muestra cómo varias operaciones se dividen en etapas (en magenta, imagen tomada deaquí):
Hipotéticamente, uncount()
¿La acción al final de esa cadena sería parte de la misma etapa final, y me garantizarían que los acumuladores utilizados en el último mapa no incluirán ningún duplicado?
¡La aclaración sobre este tema sería genial! Gracias.