[Apache Flink?]
- 분산 스트림 처리를 하는 엔진으로 "unbounded", "bounded" 데이터에 대해 상태가 있는 (stateful) 스트림 처리를 하는데 적합한 프레임 워크
- 비슷한 프레임워크들 중에 Spark, Kafka Streams, Storm 등이 있음
- Spark: 마이크로 배치
- Kafka Streams: Data Source로 Kafka만 지원함.
- Storm: Exactly Once 처리를 지원하지 않음.
[Unbounded(무한한)와 Bounded(경계있는) 데이터의 처리 ]
모든 종류의 데이터는 이벤트 스트림으로 생성될 수 있다.
ex) 카드거래, 센서측정, 로그, 웹 사이트의 사용자 행동
이러한 데이터는 Unbounded 혹은 Bounded 스트림으로 처리될 수 있다.
Unbounded Streams
시작은 있지만 끝은 없는 것. 즉, 종료되지 않고 계속해서 제공되는 데이터를 의미한다.
데이터가 계속 제공되므로 이벤트가 제공된 후 즉시 처리되어야 한다.
Bounded Streams (Batch Processing)
시작과 끝이 정의되어있는 형태. Bounded Streams를 배치 프로세싱이라고도 한다.
계산을 수행하기 전에 모든 데이터를 수집하여 처리할 수 있다.
Bounded Streams는 정렬이 가능하다.
=> Flink는 이 같은 데이터 타입들에 대해 우수한 성능을 제공한다고 한다.
[Apache Flink의 특징]
Deploy Applications Anywhere
Apache Flink는 기본적으로 분산 시스템이며 Application을 실행하기 위해 컴퓨팅 리소스를 필요로 한다.
Hadoop YARN, Apache Mesos, Kubernetes등에서 실행가능하지만 stand-alone cluster로 동작할 수도 있다.
Flink는 Flink Application들이 구성된 리소스를 자동으로 식별하고 병렬처리를 하기 위해 리소스 관리자에게 요청한다.
Run Applications at any Scale
Flink는 어떠한 규모에도 상관없이 스트리밍 애플리케이션을 실행할 수 있도록 설계되었다.
App은 클러스터에서 동시에 분산되고 실행되는 수천개의 task로 병렬화 된다.
또한 이러한 리소스들의 상태를 쉽게 관리하고, latency를 최소화하며 exactly-once를 보장한다.
현재까지 아래의 환경에서도 잘 실행된다는 것을 확인하였다.
- 하루에 수조 개의 이벤트를 처리할 수 있음
- 수 테라바이트의 상태를 유지 및 관리할 수 있음.
- 수천 개의 코어에서 실행되는 Application
Support Various Source/Sink
다양한 Source/Sink Connector들을 제공하며, 추가적으로 User-Defined Connector도 직접 만들 수 있다.
Leverage In-Memory Performance (메모리 내 성능 활용)
기본적으로 task는 메모리에서 유지되는데, 메모리를 초과하는 경우 액세스 하기 용이한 디스크 데이터 구조에 접근하여 유지한다.
이를 통해 모든 작업의 처리시간을 매우 짧게 유지할 수 있으며, 현재 상태를 주기적으로 체크하는 방식을 통해 Exactly-Once 를 보장한다.
[Applications]
Apache Flink는 unbounded, bounded 데이터 스트림에 대한 stateful 연산을 위한 프레임워크이다.
Flink는 다양한 추상화 수준에서 여러 API를 제공하고, 일반적인 사용 사례를 위한 전용 라이브러리를 제공한다.
Building Blocks for Streaming Applications
스트림 처리 애플리케이션을 위한 구성요소를 설명하고 이를 처리하기 위한 Flink의 접근 방식을 설명한다.
Flink는 아래와 같은 용어를 사용한다.
- Input Stream: Source
- Operation: Transformation
- Ouput Stream: Sink
Streams
스트림은 스트림 프로세싱의 기본 구성 요소이다.
그런데 스트림도 종류가 있으며 Flink는 이러한 처리를 모두 지원한다.
- Bounded and unbounded streams
- Real-time and recorded streams
Parallel Dataflows
Flink는 분산환경에서 각각의 Operator들이 병렬처리를 할 수 있다.
Stream이 여러 Stream partiton으로 구성될 수 있고, Operator도 Operator subtasks로 나뉠 수 있다고 한다.
State
스트리밍 Application은 기본적으로 상태를 저장해야 한다.
비즈니스 로직을 수행하는 응용프로그램은 이벤트 혹은 중간 결과를 기억한 상태에서 나중에 액세스해야 한다.
Application state는 Flink에서 가장 중요한 요소이다 (first-class citizen).
state 처리의 맥락에서 Flink가 제공하는 기능들을 보면 state를 얼마나 중요시하는지 알 수 있다.
- Multiple State Primitives
- Pluggable State Backends: Application 상태는 pluggable state backend에 의해 체크포인트가 관리되며, Flink 메모리나 RocksDB에 상태를 저장한다.
- Exactly-once state consistency: Flink 체크포인트 알고리즘은 장애가 발생하는 경우에도 프로그램의 정확성을 보장한다.
- Very Large State: Flink는 async 및 incremental checkpoint 알고리즘을 통해 수 테라바이트의 데이터를 처리하는 Application상태도 충분히 유지할 능력이 된다.
Time
시간은 스트리밍 Application에서 중요한 요소 중 하나이다.
이벤트의 측면에서 시간은 Windows 집계, 세션화, 패턴 감지 및 시간 기반의 조인과 같은 많은 동작에서 스트림 프로세싱은 시간을 기반으로 처리한다.
Flink에는 3가지 종류의 시간이 있다.
- Evebt Time: 데이터가 발생한 시간
- Ingestion Time: 데이터가 Flink로 유입된 시간
- Processing Time: 데이터가 처리된 시간
Layered APIs
Flink는 3개의 계층화된 API를 제공한다.
각 계층은 간결함과 표현력 사이에서 다양한 사용사례를 제공한다.
Checkpoints for Fault Tolerance
Flink는 checkpoint라는 이름으로 Fault Tolerance 기능을 구현하고 있다.
이 방식은 스트림의 중간에 checkpoint 를 끼워넣어 ack를 구현하는 개념이라고 한다.
만약 fault가 발생하면 checkpoint부터 다시 처리하는 방식이다.
모든 레코드에 checkpoint를 끼워넣는 것이 아니라서 빠른 성능을 보여준다고 한다.
[Use-Cases]
Event-Driven Applications
전통적인 Applicatio은 Remote DB에 지속적으로 기록하는 형태.
이벤트 기반 Application은 로컬에 상태를 저장하면서 비동기적으로 체크포인트를 Persistent Storage에 기록하는 형태.
→ 원격 데이터베이스에 기록하는 대신 로컬에 하므로 더 나은 성능.
→ 원격 데이터베이스가 변경되는 경우 전체적인 영향을 끼치는데, 이벤트 기반 애플리케이션의 경우 변경이 있어도 자체적인 변경이라 조정이 덜 필요하게 됨.
사용예시
- 사기감지
- 이상 감지
- 규칙 기반 알림
- 비즈니스 모니터링
- 웹 애플리케이션 (소셜 네트워크)
Data Analytic Applications
전통적인 배치 분석은 기록된 이벤트를 주기적으로 읽어 처리하며 결과를 업데이트하려면 전체 배치를 한 번 돌려야 한다.
그런데 스트리밍 분석은 들어오는 데이터를 지속적으로 업데이트하는 방식으로 처리한다.
사용예시
- 네트워크 품질 모니터링
- 대규모 그래프 분석
Data Pipeline Applications
ETL(extract-transform-load)는 스토리지 시스템 간에 데이터를 변환하고 이동하는 것을 뜻한다.
고전적인 ETL은 Job이 있고, Job이 주기적으로 읽어 Target에 써준다.
데이터 파이프라인은 ETL작업과 매우 유사한 용도로 사용된다.
데이터를 주기적으로 읽어오는 대신 스트리밍으로 동작하여 매우 짧은 지속시간으로 꾸준히 써서 데이터를 이동하게되는 방식이다.
데이터를 지속적으로 이동시키기 때문에 실시간으로 더 많은 사례에 활용할 수 있다.
ETL의 경우 Flink의 SQL Interface나 Table API를 통해 실현할 수 있으며, 좀 더 구체적인 작업은 DataStream API를 사용하여 데이터 파이프라인을 구축할 수 있다.
Kafka, ES, JDBC 데이터베이스 시스템과 같은 다양한 스토리지에 Data Pipeline을 구축할 수 있도록 한다.
사용예시
- 이커머스에서 실시간 검색 인덱스 구축
- 이커머스에서 실시간 ETL
[다른 Streaming 플랫폼과의 비교]
Spark
Spark는 기본적은 Non-native Streaming이다. 즉 batch job을 매우 잘게 쪼개서 Streaming을 구현하는 방식임.
자체적인 Spark Platform이 있다면 사용하는 것이 낫다.
Kafka Streams
Native Streaming.
Kafka라는 이벤트 스트리밍 엔진 위에서 돌아가도록 설계된 것이므로 내부적인 토픽에서 읽어서 처리하려고하면 Kafka Streams를 그냥 쓰는게 편하다고 함.
Flink
좀 더 빠르고 전문적으로 스트림 프로세싱을 처리하려고 한다면 사용하라고 함.
다양한 Source, Target을 제공하므로 Kafka Streams보다 유연함.
예제를 통한 차이 비교
https://dzone.com/articles/kafka-stream-kstream-vs-apache-flink
대부분의 의견
- Source가 Kafka에 밀접하게 연관되어 있다면 굳이 Flink를 쓸 필요가 없다. (Kafka Streams API, KsqlDB, Kafka Connector를 활용해라)
- Spark 는 유사 스트리밍이다. (Non-native Streaming) Spark Platform (Databricks, Amazon EMR) 이 갖추어져 있지 않은 환경이라면 굳이 추천하진 않는다.
- Flink는 HA, Fault-Tolerance, 다양한 배포모드를 지원한다.
- Flink는 Source, Sink를 다양하게 제공한다.
[Flink Kafka Connector 예제 코드 작성해보기]
코드 난이도가 어떤지 궁금해서.. 샘플로 하나 짜봄.
Kafka에서 메시지를 읽어서 소문자로 변환하는 내용임.
public static void main(String[] args) throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//Kafka에서 메시지 읽기
DataStream<String> stream = readFromKafka(env);
// 받은 메시지를 소문자로 변환 후 출력
stream.map(value -> value.toLowerCase()).print();
// execute program
env.execute();
}
public static DataStream<String> readFromKafka(StreamExecutionEnvironment env) {
env.enableCheckpointing(5000);
// set up the execution environment
Properties properties = new Properties();
properties.setProperty("bootstrap.servers", "localhost:9092");
properties.setProperty("group.id", "jaeshim-20220521-group");
DataStream<String> stream = env.addSource(
new FlinkKafkaConsumer09<>("jaeshim-20220521", new SimpleStringSchema(), properties));
return stream;
}
결과
14:21:00,416 INFO org.apache.flink.runtime.checkpoint.CheckpointCoordinator - Completed checkpoint 1 (in 579 ms)
1> SSXVNJHPDQ
1> ssxvnjhpdq
[Data Pipelines & ETL & Connector]
https://nightlies.apache.org/flink/flink-docs-master/docs/learn-flink/etl/
Apache Flink의 매우 일반적인 사용 사례 중 하나는 ETL pipeline을 구축하는 것이다.
문서에 따르면 Flink는 이를 매우 잘 지원한다고 함..
Layer 별로 제공하는 Connector들이 조금씩 달라서 구분해놓았다.
Table API, SQL With Connector
https://nightlies.apache.org/flink/flink-docs-master/docs/connectors/table/overview/
Table API를 사용하는 기본제공 Connector들의 목록
Flink의 Table API & SQL 프로그램은 다른 외부 시스템과 연결되어서 배치, 스트리밍 테이블을 읽을 수 있다.
테이블 소스는 DB, Key-Value 저장소, 메시지 큐와 같은 외부 시스템에서 데이터를 읽어서 외부 시스템으로 데이터를 내보낸다.
기본적인 Connector들이 많이 제공되지만 사용자정의 Connector를 정의해서 사용할 수도 있다.
Elasticsearch는 Sink만 지원한다.
How to use connectors
SQL문에 외부 시스템에 연결하기 위한 값을 key-value 형식으로 구성한다.
예제1: Kafka Connector
https://nightlies.apache.org/flink/flink-docs-release-1.15/docs/connectors/table/kafka/
Java, Scala, Python에 Dependency를 추가하는 방식으로 사용해볼 수 있다고 함.
SQL문과 Connector를 사용해서 쿼리를 짜는 식으로해서 연결할 수도 있는듯.
CREATE TABLE MyUserTable (
-- declare the schema of the table
`user` BIGINT,
`message` STRING,
`rowtime` TIMESTAMP(3) METADATA FROM 'timestamp', -- use a metadata column to access Kafka's record timestamp
`proctime` AS PROCTIME(), -- use a computed column to define a proctime attribute
WATERMARK FOR `rowtime` AS `rowtime` - INTERVAL '5' SECOND -- use a WATERMARK statement to define a rowtime attribute
) WITH (
-- declare the external system to connect to
'connector' = 'kafka',
'topic' = 'topic_name',
'scan.startup.mode' = 'earliest-offset',
'properties.bootstrap.servers' = 'localhost:9092',
'format' = 'json' -- declare a format for this system
)
[한 줄 소감]
아직 감이 잘 없다..
좋은지 나쁜지 구성하기는 쉬운지, 운영하기는 쉬운지.. 아직 잘은 모르겠다.
[함께 볼만한 도서]
아파치 플링크로 하는 스트림 데이터 처리 : 상태가 있는 스트림 데이터 분석
[참조]
공식페이지: https://flink.apache.org/
예제: https://www.baeldung.com/kafka-flink-data-pipeline
'Data Pipeline > Apache Flink' 카테고리의 다른 글
Kubernetes에 Apache Flink 구성해보기 (0) | 2022.12.01 |
---|