|
| 1 | +## 챕터 4 카프카 상세 개념 설명 |
| 2 | + |
| 3 | +### 4.1 토픽과 파티션 |
| 4 | + |
| 5 | +토픽은 카프카의 시작과 끝이다. |
| 6 | + |
| 7 | +토픽을 삭제하면 데이터는 삭제되고 파이프라인은 중단된다. |
| 8 | + |
| 9 | +### 4.1.1 적정 파티션 개수 |
| 10 | + |
| 11 | +토픽의 파티션 개수는 카프카의 성능과 관련이 있다. |
| 12 | + |
| 13 | +``` |
| 14 | +토픽 생성 시 파티션 개수 고려사항 |
| 15 | +- 데이터 처리량 |
| 16 | +- 메시지 키 사용 여부 |
| 17 | +- 브로커, 컨슈머 영향도 |
| 18 | +``` |
| 19 | + |
| 20 | +파티션은 카프카의 병렬처리의 핵심이다. |
| 21 | + |
| 22 | +파티션의 개수가 많아지면 많아질수록 1:1 매핑되는 컨슈머 개수가 늘어나기 때문이다. |
| 23 | + |
| 24 | +파티션 개수를 정할 때는 해당 토픽에 필요한 데이터 처리량을 측정하여 정하는 것이 중요하다. |
| 25 | + |
| 26 | +- 데이터 처리 속도 향상 방법 2가지 |
| 27 | +1. 컨슈머의 처리량을 늘리는 것 |
| 28 | + |
| 29 | + 컨슈머가 실행되는 서버의 사양을 올리는 스케일 업을 하거나 GC 튜닝 등을 활용 |
| 30 | + |
| 31 | +2. 컨슈머를 추가해서 병렬처리량을 늘리는 것 |
| 32 | + |
| 33 | +파티션 개수를 늘리고 파티션 개수만큼 컨슈머를 추가하는 방법은 데이터 처리량을 늘리는 가장 확실한 방법 |
| 34 | + |
| 35 | +만약 프로듀서가 보내는 데이터가 초당 1,000 레코드이고 컨슈머가 처리할 수 있는 데이터가 초당 100레코드라면 최소한으로 필요한 파티션 개수는 10개이다. |
| 36 | + |
| 37 | +``` |
| 38 | +프로듀서 전송 데이터량 < 컨슈머 데이터 처리량 x 파티션 개수 |
| 39 | +``` |
| 40 | + |
| 41 | +만약 전체 컨슈머 데이터 처리량이 프로듀서가 보내는 데이터보다 적담녀 컨슈머 랙이 생기고, 데이터 처리 지연이 발생하게 된다. 그렇기 때문에 컨슈머 전체 데이터 처리량이 프로듀서 데이터 처리량보다 많아야 한다. |
| 42 | + |
| 43 | +컨슈머 데이터 처리량을 구하고 난 뒤에는 프로듀서가 보내는 데이터양을 하루, 시간, 분 단위로 쪼개서 예측한다. 먄약 데이터의 지연이 절대로 발생하면 안 된다면 프로듀서가 보내는 데이터의 최대치를 데이터 생성량으로 잡고 계산하면 된다. |
| 44 | + |
| 45 | +프로듀서가 보내는 데이터양이 컨슈머의 데이터 처리량보다 작을 때 컨슈머 랙이 줄어든다. |
| 46 | + |
| 47 | +파티션의 개수를 무조건 늘리는 것만이 능사가 아니다. 파티션 개수를 늘리게 됨에 따라 컨슈머, 브로커의 부담이 있기 때문이다. |
| 48 | + |
| 49 | +메시지 키 사용 여부를 정한다. 메세지 키를 사용함과 동시에 데이터 처리 순서를 지켜야 하는 경우에 대해 고려해야 한다. 메시지 키 사용 여부는 데이터 처리 순서와 밀접한 연관이 있다. 메시지 키를 사용하면 프로듀서가 토픽으로 데이터를 보낼 때 메시지 키를 해시 변환하여 메시지 키를 파티션에 매칭시킨다. |
| 50 | + |
| 51 | +파티션 개수가 달라지는 순간 메세지 키를 사용하는 컨슈머는 특정 메세지 키의 순서를 더는 보장받지 못한다. 파티션을 변환하기 이전과 이후 메세지 키의 파티션 위치가 달라지기 때문이다. |
| 52 | + |
| 53 | +메시지 키를 사용하고 컨슈머에서 메시지 처리 순서가 보장되어야 한다면 최대한 파티션의 변화가 발생하지 않는 방향으로 운영해야 한다. |
| 54 | + |
| 55 | +메시지 키를 사용하지만 데이터 처리 순서를 지키지 않아도 된다면 파티션 개수를 처음부터 넉넉하게 잡지 않아도 된다. 데이터의 양에 따라 파티션을 늘리면 되기 때문이다. |
| 56 | + |
| 57 | +브로커와 컨슈머의 영향도. |
| 58 | + |
| 59 | +카프카에서 파티션은 각 브로커의 파일 시스템을 사용하기 때문에 파티션이 늘어나는 만큼 브로커에서 접근하는 파일 개수가 많아진다. 운영체제에서는 프로세스당 열 수 있는 파일 최대 개수를 제한하고 있다. |
| 60 | + |
| 61 | +카프카 브로커가 접근하는 파일 개수를 안정적으로 유지하기 위해서는 각 브로커당 파티션 개수를 모니터링해야 한다. 데이터양이 많아져서 파티션 개수를 늘려야 하는 상황이라면 브로커당 파티션 개수를 확인하고 진행한다. |
| 62 | + |
| 63 | +### 4.1.2 토픽 정리 정책 ( cleanup.policy ) |
| 64 | + |
| 65 | +토픽의 데이터는 시간 또는 용량에 따라 삭제 규칙을 적용할 수 있다. 또는 삭제를 원치 않는다면 카프카 클러스터가 살아있는 한 토픽의 데이터를 삭제하지 않도록 할 수도 있다. |
| 66 | + |
| 67 | +데이터를 더는 사용하지 않을 경우에는 cleanup.policy 옵션을 사용하여 데이터를 삭제할 수 있는데, cleanup.policy 옵션은 2가지 삭제 정책을 제공한다. |
| 68 | + |
| 69 | +1. delete : 데이터의 완전 삭제 |
| 70 | +2. compact : 동일 메세지 키의 가장 오래된 데이터를 삭제 |
| 71 | + |
| 72 | +- 토픽의 삭제 정책 |
| 73 | + |
| 74 | +대부분의 토픽의 cleanup.policy를 delete로 설정. |
| 75 | + |
| 76 | +토픽의 데이터를 삭제할 때는 세그먼트 단위로 삭제를 진행. |
| 77 | + |
| 78 | +세그먼트는 토픽의 데이터를 저장하는 명시적인 파일 시스템 단위. |
| 79 | + |
| 80 | +세그먼트는 파티션마다 별개로 생성되며 세그먼트의 파일 이름은 오프셋 중 가장 작은 값이 된다. |
| 81 | + |
| 82 | +segment.bytes 옵션으로 1개의 세그먼트 크기를 설정할 수 있다. |
| 83 | + |
| 84 | +segment.bytes 크기보다 커질 경우에는 기존에 적재하던 세그먼트 파일을 닫고 새로운 세그먼트를 열어서 데이터를 저장. |
| 85 | + |
| 86 | +데이터를 저장하기 위해 사용 중인 세그먼트를 액티브 세그먼트라고 한다. |
| 87 | + |
| 88 | +삭제 정책이 실행되는 시점은 시간 또는 용량이 기준이 된다. |
| 89 | + |
| 90 | +[retention.ms](http://retention.ms) 는 토픽의 데이터를 유지하는 기간을 밀리초로 설정할 수 있다. |
| 91 | + |
| 92 | +retention.bytes는 토픽의 최대 데이터 크기를 제어. |
| 93 | + |
| 94 | +- 토픽의 압축 정책 |
| 95 | + |
| 96 | +일반적으로 생각하는 zip이나 tar압축과는 다른 개념 |
| 97 | + |
| 98 | +압축이란 메시지 키별로 해당 메시지 키의 레코드 중 오래된 데이터를 삭제하는 정책을 뜻한다. |
| 99 | + |
| 100 | +오래된 데이터를 삭제하기 때문에 삭제 정책과 다르게 1개 파티션에서 오프셋의 증가가 일정하지 않을 수 있다. |
| 101 | + |
| 102 | +토픽의 압축 정책은 카프카 스트림즈 KTabel과 같이 메시지 키를 기반으로 데이터를 처리할 경우 유용하다. 데이터의 흐름이 아닌 가장 마지막으로 업데이터된 메시지 키의 데이터가 중요할 경우 가장 최신의 데이터를 제외한 나머지 데이터들을 삭제할 수 있기 때문이다. |
| 103 | + |
| 104 | +데이터의 압축 시작 시점은 min.cleanup.dirty.ratio 옵션값을 따른다. |
| 105 | + |
| 106 | +액티브 세그먼트를 제외한 세그먼트에 남아 있는 데이터의 tail 영역의 레코드 개수와 head 영역의 레코드 개수의 비율을 뜻한다. |
| 107 | + |
| 108 | +tail 영역의 레코드들은 클린 로그 라고 부르고 압축이 완료됐기 때문에 tail 영역에는 중복된 메시지 키가 없다. head 영역의 레코드들은 더티 로그라고 부르고 압축이 되기 전 레코드들이 있으므로 중복된 메시지 키를 가진 레코드들이 있다. |
| 109 | + |
| 110 | +‘더티 비율’은 더티 영역의 메시지 개수를 압축 대상 세그먼트에 남아있는 데이터의 총 레코드 수로 나눈 비율을 뜻한다. |
| 111 | + |
| 112 | +### 4.1.3 ISR |
| 113 | + |
| 114 | +ISR은 리더 파티션과 팔로워 파티션이 모두 싱크가 된 상태를 뜻한다. |
| 115 | + |
| 116 | +동기화가 완료됐다는 의미는 리더 파티션의 모든 데이터가 팔로워 파티션에 복제된 상태를 말하기 때문. |
| 117 | + |
| 118 | +ISR이라는 용어가 나온 이유는 팔로워 파티션이 리더 파티션으로부터 데이터를 복제하는 데에 시간이 걸리기 때문. |
| 119 | + |
| 120 | +리더 파티션에 데이터가 적재된 이후 팔로워 파티션이 복제하는 시간차 때문에 오프셋 차이가 발생하낟. 이런 차이를 모니터링하기 위해 리더 파티션은 [replia.lag.time.max.ms](http://replia.lag.time.max.ms) 만큼의 주기를 가지고 팔로워 파티션이 데이터를 복제하는지 확인한다. |
| 121 | + |
| 122 | +만약 팔로워 파티션이 [replica.lag.time.max.ms](http://replica.lag.time.max.ms) 보다 더 긴 시간동안 데이터를 가져가지 않는다면 해당 파티션에 문제가 생긴 것으로 판단하고 ISR 그룹에서 제외한다. |
| 123 | + |
| 124 | +ISR로 묶인 리더 파티션과 팔로워 파티션은 파티션에 존재하는 데이터가 모두 동일하기 때문에 팔로워 파티션은 리더 파티션으로 새로 선출될 자격을 가진다. |
| 125 | + |
| 126 | +ISR이 아닌 팔로워 파티션을 리더 파티션으로 선출 가능한지 여부를 선택하기 위해서는 unclean.leader.election.enable 옵션을 false 또는 true로 설정하면 된다. |
| 127 | + |
| 128 | +일부 데이터가 유실되더라도 토픽과 연동 중인 서비스의 무중단 운영이 더 중요하다면 true로 설정하면 되고, 데이터가 유실되면 안되는 경우에는 false로 설정해야 한다. |
| 129 | + |
| 130 | +## 4.2 카프카 프로듀서 |
| 131 | + |
| 132 | +### 4.2.1 acks 옵션 |
| 133 | + |
| 134 | +복제 개수가 1인 경우에 acks 옵션에 따른 성능 변화는 크지 않다. |
| 135 | + |
| 136 | +- acks=0 |
| 137 | + |
| 138 | +프로듀서가 리더 파티션으로 데이터를 전송했을 때 리더 파티션으로 데이터가 저장되었는지 확인하지 않는다는 뜻이다. |
| 139 | + |
| 140 | +프로듀서는 전송을 하자마자 데이터가 저장되었음을 가정하고 다음 데이터를 전송하기 때문에 데이터 전송이 실패한 경우를 알 수 없다. 따라서 retries 가 2 이상으로 설정되어 있더라도 재시도를 하지 않기 때문에 retires 옵션값은 무의미하다. |
| 141 | + |
| 142 | +acks를 1또는 all로 했을 경우보다 훨씬 빠르다. |
| 143 | + |
| 144 | +- acks=1 |
| 145 | + |
| 146 | +프로듀서는 보낸 데이터가 리더 파티션에만 정상적으로 적재되었는지 확인한다. |
| 147 | + |
| 148 | +- acks=all, ack=-1 |
| 149 | + |
| 150 | +프로듀서는 보낸 데이터가 리더 파티션과 팔로워 파티션에 모두 정상적으로 적재되었는지 확인한다. |
| 151 | + |
| 152 | +acks를 all로 설정할 경우에는 토픽 단위로 설정 가능한 min.insync.replicas 옵션에 따라 데이터의 안정성이 달라진다. all 옵션값은 모든 리더 파티션과 팔로워 파티션의 적재를 뜻하는 것은 아니고 ISR에 포함된 파티션들을 뜻하는 것이기 때문 |
| 153 | + |
| 154 | +min.insync.replicas를 설정할 때는 복제 개수도 함께 고려해야 한다. |
| 155 | + |
| 156 | +절대로 브로커 개수와 동일한 숫자로 설정하면 안 된다는 것. |
| 157 | + |
| 158 | +토픽별 min.insync.replicas 옵션값은 브로커 개수 미만으로 설정해서 운영해야 한다. |
| 159 | + |
| 160 | +토픽의 복제 개수는 3, min.insync.replicas를 2로 설정하고 프로듀서는 acks를 all로 설정하는 것을 추천한다. |
| 161 | + |
| 162 | +### 4.2.2 멱등성 프로듀서 |
| 163 | + |
| 164 | +멱등성이란 여러 번 연산을 수행하더라도 동일한 결과를 나타내는 것을 뜻한다. 적어도 한번 전달이란 프로듀서가 클러스터에 데이터를 전송하여 저장할 때 적어도 한 번 이상 데이터를 적재할 수 있고 데이터가 유실되지 않음을 뜻한다. 데이터의 중복이 발생할 수 있다. |
| 165 | + |
| 166 | +enable.idempotence. 옵션의 기본값은 false이며 정확히 한번 전달을 위해서는 true로 옵션값을 설정해서 멱등성 프로듀서로 동작하도록 만들면 된다. |
| 167 | + |
| 168 | +프로듀서 PID와 시퀀스 넘버를 함께 전달한다. |
| 169 | + |
| 170 | +멱등성 프로듀서는 동일한 세션에서만 정확히 한번 전달을 보장한다. 세션은 PID의 생명주기를 뜻한다. |
| 171 | + |
| 172 | +enable.idepotence 를 true로 설정하면 정확히 한번 적제하는 로직이 성립되기 위해 프로듀서의 일부 옵션들이 강제로 설정된다. 프로듀서의 데이터 재전송 횟수를 정하는 retries는 기본값으로 Integer.MAX_VALUE로 설정되고 acks 옵션은 all로 설정된다. |
| 173 | + |
| 174 | +### 4.2.3 트랜잭션 프로듀서 |
| 175 | + |
| 176 | +카프카의 트랜잭션 프로듀서는 다수의 파티션에 데이터를 저장할 경우 모든 데이터에 대해 동일한 원자성을 만족시키기 위해 사용된다. 원자성을 만족시킨다는 의미는 다수의 데이터를 동일 트랜잭션으로 묶음으로써 전체 데이터를 처리하거나 전체 데이터를 처리하지 않도록 하는 것을 의미. |
| 177 | + |
| 178 | +트랜잭션 프로듀서를 사용하려면 enable.idepotence를 true로 설정하고 [transactional.id](http://transactional.id) 를 임의의 String 값으로 정의한다. 컨슈머의 isolation.level을 read_commited 로 설정하면 프로듀서와 컨슈머는 트랜잭션으로 처리 완료된 데이터만 쓰고 읽게 된다. |
| 179 | + |
| 180 | +트랜잭션은 파티션의 레코드로 구분한다. 트랜잭션 레코드는 실질적인 데이터는 가지고 있지 않으며 트랜잭션이 끝난 상태를 표시하는 정보만 가지고 있다. |
| 181 | + |
| 182 | +## 4.3 카프카 컨슈머 |
| 183 | + |
| 184 | +### 4.3.1 멀티 스레드 컨슈머 |
| 185 | + |
| 186 | +카프카는 처리량을 늘리기 위해 파티션과 컨슈머 개수를 늘려서 운영할 수 있다. 파티션을 여러 개로 운영하는 경우 데이터를 병렬 처리하기 위해서 파티션 개수와 컨슈머 개수를 동일하게 맞추는 것이 가장 좋은 방법이다. |
| 187 | + |
| 188 | +멀티 스레드 애플리케이션으로 개발할 경우 하나의 프로세스 내부에 스레드가 여러 개 생성되어 실행되기 때문에 하나의 컨슈머 스레드에서 예외상황이 발생할 경우 프로세스 자체가 종료될 수 있고 이는 다른 컨슈머 스레드에까지 영향을 미칠 수 있다. |
| 189 | + |
| 190 | +컨슈머 스레드들이 비정상적으로 종료될 경우 데이터 처리에서 중복 또는 유실이 발생할 수 있기 때문이다. |
| 191 | + |
| 192 | +컨슈머를 멀티 스레드로 활용하는 방법 2가지 |
| 193 | + |
| 194 | +1. 컨슈머 스레드는 1개만 실행하고 데이터 처리를 담당하는 워커 스레드를 여러 개 실행하는 방법인 멀티 워크 스레드 전략이다. |
| 195 | + |
| 196 | +주의사항 |
| 197 | + |
| 198 | +1. 스레드를 사용함으로써 데이터 처리가 끝나지 않았음에도 불구하고 커밋을 하기 때문에 리밸런싱, 컨슈머 장애 시에 데이터 유실이 발생할 수 있다는 점 |
| 199 | +2. 레코드 처리의 역전현상 |
| 200 | + |
| 201 | + 레코드 처리에 있어 중복이 발생하거나 데이터의 역전현상이 발생해도 되며 매우 빠른 처리 속도가 필요한 데이터 처리에 적합 |
| 202 | + |
| 203 | +1. 카프카 컨슈머 멀티 스레드 전략 |
| 204 | + |
| 205 | + 하나의 파티션은 동일 컨슈머 중 최대 1개까지 할당. 하나의 컨슈머는 여러 파티션에 할당될 수 있다. |
| 206 | + |
| 207 | + |
| 208 | +### 4.3.2 컨슈머 랙 |
| 209 | + |
| 210 | +컨슈머 랙은 토픽의 최신 오프셋과 컨슈머 오프셋 간의 차이다. |
| 211 | + |
| 212 | +프로듀서가 보내는 데이터양이 컨슈머의 데이터 처리량보다 크다면 컨슈머 랙은 늘어난다. |
| 213 | + |
| 214 | +컨슈머 랙을 확인하는 방법 3가지 |
| 215 | + |
| 216 | +1. 카프카 명령어를 사용 |
| 217 | +2. 컨슈머 애플리케이션에서 mterics() 메서드를 사용 |
| 218 | +3. 외부 모니터링 툴 사용 |
| 219 | + |
| 220 | +### 4.3.3 컨슈머 배포 프로세스 |
| 221 | + |
| 222 | +1. 중단 배포 |
| 223 | +2. 무중단 배포 |
| 224 | + |
| 225 | + 블루/그린 배포 ⇒ 이전 버전과 신규 버전을 동시에 띄우고 트래픽 전환하기. 이건 파티션 개수와 컨슈머 개수를 동일하게 실행하는 애플리케이션을 운영할 때 유용. |
| 226 | + |
| 227 | + 롤링 배포 ⇒ 파티션 개수와 인스턴스 개수와 같거나, 그보다 많아야 한다는 점. |
| 228 | + |
| 229 | + 파티션 개수가 많을수록 리밸런스 시간도 길어지므로 파티션 개수가 많지 않은 경우에 효과적. |
| 230 | + |
| 231 | + 카나리 배포 ⇒ 사전 테스트를 하고 완료되면 나머지 파티션에 할당된 컨슈머를 롤링 또는 블루/그린 배포 |
| 232 | + |
| 233 | + |
| 234 | +### 4.4 스프링 카프카 |
| 235 | + |
| 236 | +코드적인 내용. |
0 commit comments