컨슈머 랙과 처리량 튜닝
랙이란
| 항목 | 값 |
|---|
| 파티션 최신 오프셋 | 1,000,000 |
| 컨슈머 커밋 오프셋 | 980,000 |
| lag | 20,000건. 밀린 양이다 |
- 절대값보다 추세가 중요하다. 증가 중이면 소비 속도가 생산 속도보다 느리다는 뜻
- 건수 대신 시간으로 환산(몇 분치 밀렸나)하면 서비스 영향 판단이 쉽다
증상별 처방
| 증상 | 원인 | 처방 |
|---|
| 특정 파티션만 랙 | 핫 키 편중 | 파티션 키 재설계 |
| 전 파티션 랙 증가 | 소비 처리 자체가 느림 | 하류 IO 배치화, 파티션과 컨슈머 동시 증설 |
| 랙이 톱니 모양 반복 | 리밸런싱 반복 | 한 번에 가져오는 건수 축소, 폴 간격 조정 |
| CPU는 한가한데 느림 | IO, 커밋 대기 | 배치 커밋, 프리페치 조정, 병렬 워커 |
랙이 늘어나는 것과 밀린 것을 구분한다
같은 숫자여도 뜻이 다릅니다. 기울기를 봐야 처방이 갈립니다.
| 모양 | 뜻 | 할 일 |
|---|
| 계속 오른다 | 들어오는 양이 처리량보다 크다 | 처리량을 늘린다 |
| 높지만 평평하다 | 한 번 밀렸고 지금은 따라간다 | 기다린다 |
| 톱니처럼 오르내린다 | 유입이 몰리는 시간대가 있다 | 몰리는 만큼 여유를 둔다 |
| 한 파티션만 오른다 | 키가 한쪽으로 쏠렸다 | 키를 다시 정한다 |
마지막이 가장 흔합니다. 전체 랙 평균만 보면 정상으로 보이는데 특정 파티션만 쌓입니다.
늘려도 안 늘어나는 순간
컨슈머를 늘리면 처리량이 오릅니다. 다만 파티션 수까지만 오릅니다.
컨슈머가 파티션보다 많으면 남는 컨슈머는 아무것도 안 받는다
파티션을 늘리는 것은 되지만 줄이는 것은 대개 안 된다
그래서 파티션 수는 지금 필요한 양이 아니라 앞으로 필요할 양으로 잡습니다. 다만 너무
크게 잡으면 파티션마다 드는 비용이 쌓입니다.
실무 포인트
- 컨슈머 수의 상한은 파티션 수다. 인스턴스만 늘려도 처리량은 오르지 않는다
- 한 건씩 DB에 쓰는 구조를 배치 삽입으로 바꾸면 수 배 개선되는 경우가 많다
- 폴 루프 안에서 오래 걸리는 작업을 하면 리밸런스가 유발되고 중복 처리가 늘어난다
- 경보는 랙 임계치와 증가율을 함께 걸어야 서서히 쌓이는 누적과 급증을 모두 잡는다
Q.컨슈머 랙이 계속 증가할 때 어떤 순서로 원인을 찾으시겠어요?
기울기부터 봅니다. 같은 숫자여도 뜻이 다릅니다.
| 모양 | 뜻 |
|---|
| 계속 오른다 | 들어오는 양이 처리량보다 크다 |
| 높지만 평평하다 | 한 번 밀렸고 지금은 따라가는 중이다 |
| 한 파티션만 오른다 | 키가 한쪽으로 쏠렸다 |
그 다음 순서입니다.
- 파티션별로 나눠 본다. 전체 평균은 정상인데 한 파티션만 쌓이는 경우가 가장 흔합니다.
- 처리 시간을 잰다. 메시지 하나에 얼마나 걸리는지 모르면 대수를 못 정합니다.
- 어디서 걸리는지 본다. 대개 외부 호출이나 DB 쓰기입니다. 컨슈머 CPU 가 한가한데
느리면 기다림이 원인입니다.
- 컨슈머 수와 파티션 수를 비교한다. 컨슈머가 파티션보다 많으면 남는 쪽은 놉니다.
- 재시도와 실패를 본다. 실패가 반복되면 같은 메시지를 계속 붙잡고 있습니다.
1번을 건너뛰면 나머지가 전부 헛수고입니다. 쏠림이 원인인데 대수를 늘리면 놀고 있는
컨슈머만 늘어납니다.
흔한 실수: 랙 숫자만 보고 바로 컨슈머를 늘리는 것. 원인이 처리 시간이면 대수를
늘려도 그대로고, 쏠림이면 아예 효과가 없습니다. 무엇이 병목인지 정한 뒤에 손댑니다.
Q.컨슈머 인스턴스를 늘렸는데 랙이 줄지 않는 이유는?
가장 흔한 이유는 파티션 수가 상한이기 때문입니다. 한 파티션은 한 컨슈머만 읽으므로
컨슈머가 파티션보다 많으면 남는 쪽은 아무것도 안 받습니다.
| 원인 | 확인 방법 |
|---|
| 컨슈머 > 파티션 | 할당 현황에서 담당 파티션이 없는 컨슈머를 본다 |
| 키 쏠림 | 파티션별 랙을 나눠 본다. 한쪽만 쌓인다 |
| 병목이 뒤에 있다 | DB나 외부 API 지표를 본다. 컨슈머는 한가하다 |
| 리밸런싱 반복 | 늘린 직후부터 재할당이 계속 돈다 |
| 한 파티션을 여러 스레드로 | 처리량은 오르지만 순서가 깨진다 |
세 번째가 특히 흔합니다. 컨슈머를 늘리면 뒤쪽 DB 로 가는 부하도 같이 늘어서, 그쪽이
포화면 전체 처리량이 그대로이거나 오히려 나빠집니다. 그때는 컨슈머가 아니라 뒤를
고쳐야 합니다.
파티션은 늘릴 수 있지만 줄이기는 대개 안 됩니다. 그리고 늘리는 순간 같은 키가 다른
파티션으로 갈 수 있어 순서 보장이 끊깁니다. 그래서 파티션 수는 지금 필요한 양이
아니라 앞으로 필요할 양으로 잡습니다.
흔한 실수: 컨슈머 수를 파티션보다 크게 잡아 두고 여유가 있다고 보는 것. 그 여유는
실제로는 놀고 있는 프로세스이고, 자원만 쓰면서 지표를 좋게 보이게 만듭니다.
Q.리밸런싱이 반복되는 원인과 대응 방법은?
리밸런싱은 그룹 구성원이 바뀌었다고 판단될 때 일어납니다. 반복된다면 컨슈머가
계속 죽었다 살아나는 것으로 보이고 있다는 뜻입니다.
| 원인 | 실제로 일어나는 일 |
|---|
| 처리가 너무 오래 걸림 | 다음 폴링까지 시간이 넘어 죽은 것으로 간주된다 |
| 하트비트 실패 | GC 정지나 네트워크 지연으로 신호가 늦는다 |
| 배포가 잦다 | 인스턴스가 뜨고 질 때마다 재할당이 돈다 |
| 처리 건수가 너무 많음 | 한 번에 가져온 양을 시간 안에 못 끝낸다 |
첫 줄과 마지막 줄이 같은 문제의 앞뒤입니다. 한 번에 500건을 가져와 건당 100ms 면
50초인데, 폴링 간격 상한이 그보다 짧으면 매번 쫓겨납니다.
대응은 셋입니다. 한 번에 가져오는 건수를 줄이거나, 폴링 간격 상한을 실제 처리 시간보다
넉넉하게 잡거나, 처리 자체를 빠르게 만드는 것입니다. 가져오는 건수를 줄이는 쪽이
가장 안전합니다. 상한만 늘리면 진짜 죽은 컨슈머를 알아채는 시간도 같이 늘어납니다.
리밸런싱 중에는 그 파티션의 처리가 멈추므로, 반복되면 랙이 계속 쌓입니다. 즉
리밸런싱 반복은 원인이자 결과로 얽힙니다.
흔한 실수: 랙이 쌓이니까 한 번에 더 많이 가져오게 설정을 키우는 것. 처리 시간이
길어져 리밸런싱이 더 자주 나고, 랙은 더 쌓입니다.
Q.코드 변경 없이 처리량을 올릴 수 있는 방법이 있나요?
설정과 구성만으로 손댈 수 있는 곳이 몇 군데 있습니다.
| 손댈 곳 | 효과 | 대가 |
|---|
| 파티션 수를 늘린다 | 병렬도가 올라간다 | 순서 보장 범위가 바뀐다. 되돌리기 어렵다 |
| 컨슈머 대수를 파티션까지 늘린다 | 즉시 효과 | 파티션 수를 넘으면 소용없다 |
| 한 번에 가져오는 건수 조정 | 왕복이 줄어 처리량이 오른다 | 너무 키우면 리밸런싱을 부른다 |
| 커밋 주기를 늘린다 | 커밋 왕복이 줄어든다 | 장애 시 다시 처리할 양이 늘어난다 |
| 압축을 켠다 | 네트워크가 병목이면 크게 는다 | CPU 를 더 쓴다 |
먼저 무엇이 병목인지 재야 합니다. 네트워크가 병목이 아닌데 압축을 켜면 CPU 만
쓰고 느려집니다. 컨슈머가 기다리기만 한다면 대수 늘리기가 듣고, CPU 가 붙어 있다면
안 듣습니다.
구성으로 가장 크게 얻는 것은 대개 한 번에 가져오는 양입니다. 건당 왕복이 지배적인
구간에서 묶음을 키우면 몇 배가 납니다. 다만 처리 시간이 폴링 상한을 넘지 않는 선까지만
올립니다.
흔한 실수: 커밋 주기를 크게 늘려 처리량을 올리고 끝내는 것. 장애가 나면 그 주기만큼
다시 처리하므로 중복 처리량이 늘어납니다. 받는 쪽이 멱등하지 않으면 그때 사고가
납니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
메시징 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.