메모리 튜닝 가이드
메모리 튜닝 가이드 (Memory tuning guide)
주 메모리 설정 가이드에 더해, 이 섹션에서는 사용 사례에 따라 메모리를 설정하는 방법과 각 사례에서 중요한 옵션을 설명합니다.
출처: 문서
본문
standalone 배포용 메모리 구성 (Configure memory for standalone deployment)
standalone 배포에서는 Flink 자체에 얼마나 많은 메모리를 줄 것인지 선언하고 싶다면, total Flink memory(taskmanager.memory.flink.size 또는 jobmanager.memory.flink.size) 또는 그 컴포넌트들을 구성하는 것이 권장됩니다. 또한 JVM metaspace가 문제를 일으키면 조정할 수 있습니다.
JVM overhead는 Flink나 배포 환경이 제어하지 않으므로 total Process memory는 관련이 없습니다. 이 경우 실행 머신의 물리적 리소스만 중요합니다.
컨테이너용 메모리 구성 (Configure memory for containers)
컨테이너화된 배포(Kubernetes 또는 Yarn)에서는 total process memory(taskmanager.memory.process.size 또는 jobmanager.memory.process.size)를 구성하는 것이 권장됩니다. 이는 Flink JVM 프로세스에 총 얼마만큼의 메모리를 할당해야 하는지 선언하며, 요청된 컨테이너 크기에 해당합니다.
total Flink memory를 구성하면 Flink는 JVM 메모리 컴포넌트를 암시적으로 더해 total process memory를 유도하고, 그 유도된 크기의 메모리로 컨테이너를 요청합니다.
경고: Flink 또는 사용자 코드가 컨테이너 크기를 초과하여 관리되지 않는 off-heap(native) 메모리를 할당하면, 배포 환경이 해당 컨테이너를 종료할 수 있으므로 job이 실패할 수 있습니다.
container memory exceeded 실패에 대한 설명도 참고하세요.
Netty4용 메모리 구성 (Configure memory for Netty4)
Apache Pekko 버전이 업데이트되면서 이제 Flink RPC도 Netty4를 사용합니다. Netty4는 Netty3에 비해 바이트 버퍼에 관한 몇 가지 변경 사항을 도입했는데 언급할 가치가 있습니다. 주로 Netty4는 pooled byte buffer를 도입하여 더 나은 성능을 가능하게 하지만, 메모리를 약간 더 할당합니다.
바이트 버퍼 할당자 유형 구성 (Configure byte buffer allocator type)
바이트 버퍼 할당자 유형을 지정하면 Flink RPC와 Flink의 shuffle 성능 모두에 영향을 미친다는 점에 유의하세요!
리소스가 매우 제한된 사용 사례에서는 이러한 구성을 세밀하게 조정하는 것이 의미 있을 수 있습니다. 이는 TaskManager/JobManager에 다음 JVM 프로퍼티를 설정하여 수행할 수 있습니다: org.apache.flink.shaded.netty4.io.netty.allocator.type. 가능한 할당자 유형은 다음과 같습니다:
pooled:PooledByteBufAllocator.DEFAULT사용unpooled:UnpooledByteBufAllocator.DEFAULT사용adaptive:AdaptiveByteBufAllocator사용
예제 (Example)
# In <flink-root-dir>/conf/config.yaml
env:
java:
opts:
jobmanager: -Dorg.apache.flink.shaded.netty4.io.netty.allocator.type=unpooled
taskmanager: -Dorg.apache.flink.shaded.netty4.io.netty.allocator.type=unpooled
이 바이트 버퍼 할당자에 대한 자세한 내용은 Netty4 문서의 관련 부분을 확인하세요.
JDK >= 11에서 리플렉션 활성화 (Enable reflection in JDK >= 11)
Flink는 기본적으로 --add-opens=java.base/java.lang.reflect=ALL-UNNAMED를 가지므로, Netty4에서 리플렉션을 사용하는 것도 대부분의 환경에서 문제가 되지 않아야 합니다. org.apache.flink.shaded.netty4.io.netty.tryReflectionSetAccessible을 설정하면 GC 압력을 줄이고 성능을 향상시키는 일부 최적화를 활성화합니다.
예제 (Example)
# In <flink-root-dir>/conf/config.yaml
env:
java:
opts:
jobmanager: -Dorg.apache.flink.shaded.netty4.io.netty.tryReflectionSetAccessible=true
taskmanager: -Dorg.apache.flink.shaded.netty4.io.netty.tryReflectionSetAccessible=true
state backend용 메모리 구성 (Configure memory for state backends)
이것은 TaskManager에만 관련됩니다.
Flink 스트리밍 애플리케이션을 배포할 때 사용되는 state backend 유형이 클러스터의 최적 메모리 구성을 결정합니다.
HashMap state backend
무상태(stateless) job을 실행하거나 HashMapStateBackend를 사용할 때는 managed memory를 0으로 설정하세요. 이렇게 하면 JVM에서 사용자 코드에 최대량의 heap 메모리가 할당되도록 보장합니다.
RocksDB state backend
EmbeddedRocksDBStateBackend는 네이티브 메모리를 사용합니다. 기본적으로 RocksDB는 네이티브 메모리 할당을 managed memory 크기로 제한하도록 설정됩니다. 따라서 상태를 위해 충분한 managed memory를 예약하는 것이 중요합니다. 기본 RocksDB 메모리 제어를 비활성화하면, RocksDB가 요청된 컨테이너 크기(total process memory) 한도를 초과하여 메모리를 할당할 경우 컨테이너화된 배포에서 TaskManager가 종료될 수 있습니다. RocksDB 메모리 튜닝 방법과 state.backend.rocksdb.memory.managed도 참고하세요.
배치 job용 메모리 구성 (Configure memory for batch jobs)
이것은 TaskManager에만 관련됩니다.
Flink의 배치 operator는 managed memory를 활용하여 더 효율적으로 실행됩니다. 이를 통해 일부 연산은 Java 객체로 역직렬화할 필요 없이 원시 데이터에 대해 직접 수행될 수 있습니다. 이는 managed memory 구성이 애플리케이션 성능에 실질적인 영향을 미친다는 것을 의미합니다. Flink는 배치 job을 위해 구성된 만큼 managed memory를 최대한 할당하고 사용하려고 시도하지만 그 한도를 넘지 않습니다. Flink는 활용해야 할 메모리가 정확히 얼마인지 알기 때문에 OutOfMemoryError를 방지합니다. managed memory가 충분하지 않으면 Flink는 디스크로 우아하게(spill) 유출합니다.