
Databricks 노트북에서 데이터 품질 체크(에러 레코드 수), 간단한 카운팅/합산, 디버깅용 메트릭을 분산 실행(Executors) 중에 모으고 싶을 때가 있습니다. 이때 가장 먼저 떠오르는 게 Spark의 Accumulator(누적기) 인데요.
하지만 “돌아가긴 하는데 숫자가 가끔 이상하다”는 경험도 흔합니다. 이 글에서는 Databricks 환경에서 Accumulator의 개념 → 사용법 → 주의사항(중요) → 대안 순으로 정리합니다.
Spark의 Driver-Executor 구조 이해가 Accumulator 이해의 출발점입니다. Source
Spark Accumulator는 여러 Executor에서 발생한 값을 “더하기(add)” 형태로 Driver에 모으는 공유 변수입니다. 핵심 제약은 다음 한 줄로 요약됩니다.
+= 또는 .add() 로 “추가”만 가능 acc.value 로 Driver만 가능 즉, “분산 작업에서 값을 모으되, 읽기는 Driver만” 허용하는 구조입니다. Source
Databricks의 PySpark API 문서도 동일하게 설명합니다. Source
“Worker에서 누적 → Driver에서 확인”이라는 방향성이 포인트. Source
Databricks 노트북에서는 보통 spark가 기본 제공되므로, sc = spark.sparkContext로 접근합니다.
sc = spark.sparkContext
acc = sc.accumulator(0) # 초기값 0
rdd = sc.parallelize([1, 2, 3])
def f(x):
global acc
acc += x
rdd.foreach(f)
acc.value
이 형태는 Spark/Databricks 문서 예시와 동일한 흐름입니다. Source
.add()로 누적하기b = sc.accumulator(0)
def g(x):
b.add(x)
rdd.foreach(g)
b.value
이 또한 공식 예시에 포함된 패턴입니다. Source
value 읽기/쓰기아래 코드는 에러가 나거나(대표적으로 Py4JJavaError), 의도한 대로 동작하지 않습니다.
acc.value를 읽기:rdd.map(lambda x: acc.value).collect() # 실패(문서 예시에서 에러)
acc.value를 직접 설정:def h(x):
global acc
acc.value = 7
rdd.foreach(h) # 실패(문서 예시에서 에러)
이 제약은 문서에 예제로 명시되어 있습니다. Source
여기부터가 실전입니다. Accumulator는 디버깅/관측용으로는 유용하지만, 아래 상황에서 과대 카운트(over-count) 같은 문제가 생길 수 있습니다.
이런 이유로 “실패 복구 과정에서 같은 작업이 여러 번 실행되며 누적이 중복 반영될 수 있다”는 비판이 잘 알려져 있습니다. Source
결론적으로, 품질검사 실패 기준(예: 에러 50개 넘으면 잡 실패) 같은 “정확해야 하는 로직”을 Accumulator 값 하나에 걸면 위험해질 수 있습니다. (특히 셔플/재시도 가능성이 있는 작업)
Databricks 커뮤니티 글에서도 둘을 함께 소개합니다. 요약하면:
Databricks 커뮤니티 글의 설명도 같은 방향입니다. Source
| 구분 | 목적 | 데이터 흐름 | 수정 가능? | 대표 사례 |
|---|---|---|---|---|
| Accumulator | 분산 태스크의 값 “모으기” | Executor → Driver | Executor는 add만, Driver가 조회 | 에러 레코드 수, 스킵 건수 |
| Broadcast | 큰 읽기전용 값 “뿌리기” | Driver → Executor | 읽기 전용 | 룩업 테이블, 설정값 |
Databricks에서도 Spark 실행 모델(Driver/Worker) 위에서 Accumulator가 동작합니다. Source
재시도/재계산에서 누적이 예상치 못하게 증가할 수 있다는 점은 강하게 경고됩니다. Source
df.filter(...).count(), groupBy().agg(...)