Kafka의 리밸런싱 븡식은 적극적 리밸런싱과 협력적 리밸런싱이 나뉘며 각각 4가지의 파티션 할당 종류가 존재한다. 범위(Range) 파티션 할당 전략 - 적극적 리밸런싱 라운드 로빈(RoundRobin) 파티션 할당 전략 - 적극적 리밸런싱 스티키(Sticky) 파티션 할당 전략 - 적극적 리밸런싱 협력적 스티키(CooperativeSticky) 파티션 할당 전략 - 협력적 리밸런싱 하나씩 알아보도록 하자 범위(Range) 파티션 할당 전략 범위 파티션 할당 전략은 카프카 v2.4 버전 이전에 기본으로 설정된 적극적 리밸런싱 방식의 파티션 할당 전략이다. 범위 파티션 할당 전략은 다음과 같은 프로세스를 거친다. 구독중인 파티션과 컨슈머를 순서대로 나열한다. 이후 각 컨슈머가 받아야할 파티션의 수를 결정..
전체 글
개발만 하기는 심심하니 기록 또 기록..카프카 컨슈머는 토픽의 각 파티션에서 메시지를 처리하는 역할을 한다. 그런데, 특정 컨슈머가 문제를 겪게 되면 그 컨슈머가 처리하던 파티션의 소유관은 다른 컨슈머로 넘어가게 된다. 이런 과정을 리밸런싱이라고 부르며 주로 아래와 같은 상황에서 발생한다. 컨슈머 그룹에 새로운 컨슈머가 추가 될 때 (+) 기존 컨슈머가 그룹에서 나가게 될 때 (-) 구독하는 토픽에 새로운 파티션이 생길 때 컨슈머가 구독하는 토픽이 변경될 때 리밸런싱이 가장 많이 일어나는 일반적인 상황은 애플리케이션 배포 상황이다. 기존 애플리케이션이 종료 후에 애플리케이션이 실행되면서, 기존 컨슈머가 삭제되고 새로운 컨슈머가 생성되기 때문이다. 이 과정에서 리밸런싱은 최소 두번 이상 발생한다. 리밸런싱은 아래와 같은 문제점을 동반한다. do..
JPA는 트랜잭션 기반으로 사용된다. 그래서 JPA를 사용하면 우리는 자주 @Transactional어노테이션을 사용하는 것을 알 수 있다. 그리고 조회의 경우에는 readOnly=true옵션도 함께 주게된다. 오늘은 JPA와 @Transactional에 대해서 몇 가지 궁금한 점에 대해 기록해보겠다. readOnly = true를 설정하는 이유 우리는 조회용 서비스 메서드를 작성할 때 @Transactional(readOnly = true) 이렇게 서비스 위에 어노테이션을 달아주게 된다. 이 어노테이션을 달아주게 된다면 이점이 무엇이 있을까? 가독성? 물론 가독성에 대한 장점도 있겠지만 다른 이유도 존재한다. 변경 감지 JPA의 영속성 컨텍스트가 수행하는 변경 감지(Dirty Checking)와 관련이..
애플리케이션이 여러 서버에 분산된 자원을 호출할 경우 이 자원들의 물리적 위치를 알고있어야한다. 그래서 서비스 위치 확인은 대개 DNS, Load Balancer의 조합으로 해결되었다. 전통적 시나리오에서는 서비스 소비자에게 요청받은 로드 밸런서 라우팅 테이블 항목에는 서비스를 호스팅하는 한 개 이상의 서버 목록이 존재한다. 로드 밸런서는 이 목록에서 서버 하나를 골라 요청을 전달한다. 이러한 기존 방식의 서비스 인스턴스는 한 개 이상의 애플리케이션 서버에 배포되었다. 애플리케이션의 수는 대개 고정적이었고(ex 서비스를 호스팅하는 애플리케이션의 수가 늘거나 줄지 않음) 그리고 영속적이었다. 즉 애플리케이션을 실행 중인 서버가 고장나면 사용하던 것과 동일한 IP 주소와 구성으로 복구된다. 고가용성을 위해 ..
MongoDB에서는 트랜잭션을 지원하지 않는다. 그렇기에 데이터 복구가 안된다는 한계가 있다. 여러 환경에서 데이터 복구를 구현하려면 어떻게 해야하고 어떤 것을 지원하고 있는지 알아보겠다. UNDO - 복구, 원상태 롤백 REDO - 복구, 실패시 재시도 몽고디비에서는 UNDO와 REDO가 존재하지 않는다 -> DB가 보장되지 않음 (정보가 100퍼센트 정확하하지 않는다.) 해결하기 위해서는? -> 이런 경우에는 프로그래밍 레벨에서도 처리해줄 수는 있다. (try catch 같은 것으로 실패했을 경우 다시 update, insert) 하지만 위와 같은 방법을 해도 몽고 디비가 데이터를 보장해주지는 않는다. 그렇다면 몽고디비에서는 undo, redo를 프로그래밍으로 처리할 수 밖에 없는가? 그건 아니고 방..
Namespace Namespace는 쿠버네티스의 하나의 클러스터를 여러개의 논리적인 단위로 분할하는 기술이다. 특정 애플리케이션을 띄우기위한 파드들의 집합을 분리하기 위해 사용된다. 여러 팀들이 네임스페이스를 공유할 수 있으며 쿼터 설정을 통해 자원 사용량을 제한할 수 있다. 쿠버네티스는 클러스터 다음으로 분리단위가 크기 때문에 가장 먼저 검토해야할 단위기도 하다. 네임스페이스는 여러개의 팀이 구성되어있거나, 프로젝트의 많은 사용자가 있는 환경에 적합하다. 유저 수가 적거나 수십명밖에 되지 않은 프로젝트는 사용하기에 적합하지 않다. 쿠버네티스를 처음 설치하면 기본으로 몇 개의 네임스페이스가 생성된다. kubectl 명령어로 현재 생성되어 있는 네임스페이스를 확인할 수 있다. $ kubectl get n..
Saga Pattern Saga 패턴은 트랜잭션의 관리주체가 DBMS가 아닌 애플리케이션에 있다. app이 분산되어있을 때, 각 App 하위에 존재하는 DB는 local 트랜잭션 처리만 담당한다. 따라서 각각의 app에 대한 연속적인 트랜잭션 요청 및 실패의 경우에 rollback 처리(보상 트랜잭션)을 애플리케이션에서 구현해야 한다. saga 패턴은 위 그림과 같이 연속적인 업데이트 연산으로 이루어져있으며, 전체 데이터가 동시에 영속화되는 것이 아니라 순차적인 단계로 트랜잭션이 이루어진다. 따라서 애플리케이션 비즈니스 로직에서 요구되는 마지막 트랜잭션이 끝났을 때, 데이터가 완전히 영속되었음을 인지하고 이를 종료한다 . Two Phase Commit과는 다르게 saga를 활용한 트랜잭션은 데이터 격리성..
Redis 분산락 분산락은 Race Condition이 발생할 때 하나의 공유 자원에 접근할 때 데이터에 결함이 발생하지 않도록 원자성을 보장하는 기법이다. 대표적으로 사용해볼 저장소는 Redis로 싱글스레드 기반의 NoSQL이다. 여러대의 서버들은 공통된 Redis를 바라보며 자신이 임계영역에 접근할 수 있는지 확인하고 이러한 부분에서 원자성을 확보한다. Redis도 물론 싱글스레드기반이기 때문에 단일 장애 지점이 될 수 있음을 고려하여 Failover용 추가 slave 자원을 구축해야한다. Trade-off Redis Client를 활용해서 락을 구현해 볼 것이다. Redis Client인 Redission, Lettuce를 고려해 볼 수 있다. 둘은 공통적으로 스핀락을 사용해 락을 얻으려고 시도하며..
멀티 컨테이너 파드 디자인 패턴 멀티 컨테이너 파드란? 멀티 컨테이너 파드는 한 파드내에서 여러개의 컨테이너가 구동되어 있는 형태의 파드다. 여러 컨테이너들은 같은 IP를 가지고 있으며 서로 다른 포트를 공유하고 있다. 한 파드의 여러 컨테이너들은 서로 다른 목적, 성격을 가진 컨테이너를 배치하면 안된다. 이는 쿠버네티스의 설계사상에 맞지 않는 방식이기 때문이다. 그래서 멀티 컨테이너 파드는 메인 프로세스를 네트워크 또는 스토리지의 밀접한 공유가 필요한 다른 컨테이너와 함께 운영하고자 할때 고려하는 것이 바람직하다. 이러한 멀티 컨테이너 파드를 구축할때 권장되는 디자인 패턴들이 있으며 세 가지를 알아보겠다. 그리고 마지막에는 init 파드에 대해서도 함께 알아보도록 하겠다. 위와 같이 3가지의 패턴이 존..