토스 SLASH 24 정리
토스 SLASH24 중 일부 영상을 정리한 글입니다.
리플레이 검증으로 새로운 금융 시스템 안전하게 도입하기
Verifier 개발
- 토스에서는 국내원장 차세대 프로젝트를 진행
- 운영중인 기존 C언어, Monolithic으로 구현된 원장 시스템을 Kotlin, MSA로 전환
- 다음과 같은 제약사항을 두고 전환
- API 스펙유지
- DB 스키마 유지
- 주요 비즈니스 로직 유지
- 기존 원장 시스템을 사용하
- 필요시 기존 원장으로 롤백 가능
- 어려움
- 기존 시스템 변경
- 테스트 코드 작성에 대한 리소스 부족
- 한번 통합 테스트를 위해 많은 선행 작업 필요
- Read Verifier
- Read API 검증 가동하ㅗ
- 기존 원장에 대한 요청와 응답을 비동기로 신규 원장 호출,
- 위 그림의 Verifier가 Kotlin기반 MSA의 요청, 응답 비교 결과를 저장
- 어드민에서 API별 verifier 사용여부, 사용시간, 트래픽 비율, 재시도 여부
- 일별 리포팅
- Write Verifier
- 그림
- 기존 원장에 보내기 전에 차세대 원장에서 처리
- 트랜잭션을 마치기 전에 트랜잭션 내에서 실행된 CUD 쿼리를 조회 쿼리로 변경, 조회 결과를 저장
- 조회 쿼리, 결과를 레디스에 저장
- 트랜잭션 롤백
- CUD 쿼리 -> 조회 쿼리
- 기존 원장의 요청 처리
- 요청과 응답을 Verifier로 전송
- 레디스에 저장된 쿼리, 처리결과와 비교
- 정리
- 요청을 미리 처리해보고 롤백하는 방식
- 동기식으로 동작하기 때문에 성능에 영향을 주어 개발 환경에서만 사용
- 검증을 위한 기능을 라이브러리로 제공
- 결과 리포팅
생애 주기가 긴 대출 상품
- 대출 기간이 10년인 상품이 존재
-
약정서에 명시된 약정을 향후 10년동안 정확하게 무리없이 수행하는 시스템
- 발생가능한 이벤트
- 기준금리 변경
- 기준금리만 변경되고 가산금리는 유지
- 기준금리 변경
- 개발단계에서 작성된 로직이 향후 10년동안 문제없이 동작하는것을 테스트하는 방법
- 종단 테스트에서는?
- 대출 실행, 해지, 상환 등 은 테스트가능
- 장기적인 기간에 대한 테스트
- 미래에 실행될 로직을 지금 테스트 하는 방법
- 대출 시스템이 모놀리식이라는 것을 활용
- 하나의 시스템, 하나의 데이터베이스
- 복잡하다는 단점이 있지만 한번 설정으로 대출거래 시스템 세팅 가능
- 모든 시간관련 로직이 한곳에서 제어
- 비즈니스
- 실시간 거래
- 배치 거래
- 테스트하려는 거래를 테스트환경에서 순차적으로 수행하면 동일한
- 대출 시스템이 모놀리식이라는 것을 활용
- 독립된 테스트 환경에서 시간을 바꿔가며, 거래실행(실시간, 배치), 검증
구현 레벨
대출 시스템, 데이터베이스 대출 시스템과 제어하는 에이전트는 하나의 pod에서 실행 각 pod별 독립된 테스트환경 구축 가능
시뮬레이션 마다 독립된 데이터베이스 사용
- 프로시저를 통한 복제
- 3분이내
Next 코어뱅킹, MSA와 MySQL로 여는 평생 무료 환전 시대
- 토스뱅크의 기술 전환 배경
일반적인 은행시스템은 고객 -> 채널계 -> 코어뱅킹(계정계)
- 채널계: 고객의 트래픽을 받아 코어뱅킹에 전달하는 시스템
- 코어뱅킹 (계정계): 금원과 관련된 메인 비즈니스 로직을 처리하는 시스템 (모놀리식, Oracle)
[초창기 아키텍처]
코어뱅킹 자체는 레거시(모놀리식)
- 장점
- 트랜잭션 처리 용이
- 단점
- 한개의 서버에서 모든 트래픽 처리
- 단일 장애 지점
- 한개의 서버에서 모든 트래픽 처리
- 모놀리식 -> 마이크로서비스
- 각 서비스들은 마이크로서비스로 분리되었지만 DB는 여전히 Oracle을 공유해서 사용
- Oracle이 단일 장애지점
- Oracle을 분리
- 비용문제 Oracle 장점
- 신뢰성과 안정성
- 확장성
- 성능
- 오랜기간 축적된 (금융)노하우 단점
- 단일장애지점
- 비싼 비용
- 제한적인 Scale-out
-
기술 비교: 원화예금 VS 외화예금 시스템 구조
-
외화예금 트랜잭션 아키텍처
동기 비동기로 분리
- 외화예금 API 뜯어보기
입금
- 잔액 변동을 막는 동시성 제어가 필수
- 24/365 무중단 환전 서비스 구현 방법
토스뱅크가 차세대를 하지 않는 이유: 지속 가능한 마이그레이션 전략
- Strangler Fig Pattern
- 대상선정
- 분석
- 설계
- 구현
- 검증
대규모 사용자 기반의 마이데이터 서비스 안정적으로 운영하기
- 70,000TPS를 처리중인 마이데이터 서비스를 다음 관점에서 소개
- 장애 대응
- 토스 시스템 부하 개선
- 피크 트래픽 제어
보상 트랜잭션으로 분산 환경에서도 안전하게 환전하기
- 토스뱅크는 모놀리식의 뱅킹 시스템을 마이크로서비스로 분리
- 팀, 도메인 등의 특성에 따라 원화계좌와 외화계좌가 분리되어 개발됨
- 데이터베이스도 분리되어있는 마이크로서비스
- 환전은 위와같이 서버와 데이터베이스가 분리된 환경에서 구현되어야 했음
- 즉 데이터베이스 레벨에서 원자성을 유지할수 없음
- 이를 위해 토스는 분산 트랜잭션을 구현해야했음
- 분산 트랜잭션으로는 대표적으로 두 가지가 존재
- Two Phase Commit (2PC): 두 단계로 구분해서 커밋 수행
- Voting
- Coordinator가 트랜잭션 참여자에게 commit 가능여부를 질의
- 트랜잭션 참여자들은 응답
- 모든 서비스가 트랜잭션 가능인경우 아래의 Commit단계 진행
- 하나의 서비스라도 커밋이 불가능한 경우 모든 서비스에 Rollback 요청
- Commit
- Coordinator가 트랜잭션 참여자에게 commit 요청
- Voting
- Saga 패턴
- 각 서비스들이 작은 로컬트랜잭션을 실행하면서 진행
- 특정 단계에서 실패하면 보상 트랜잭션 실행
- Two Phase Commit (2PC): 두 단계로 구분해서 커밋 수행
- 두 가지 방식 비교
- 토스는 환전서비스를 위해 Saga 패턴 선택
- 높은 트래픽 처리
- 다양한 트랜잭션 참여자들이 추가될 가능성이 존재
- Saga는 크게 두 가지 방식으로 구분
- [두 가지 방식의 사가 그림]
- Choreography Saga
- 중앙제어자 없이 메시지 브로커를 사용해서 이벤트 교환하며 진행
- 장점
- 단일 장애지점 없음
- 느슨한 결합
- 단점
- 현재 진행중인 트랜잭션 상태 추적/디버깅 어려움
- Orchestration Saga
- Orchestrator가 각 서비스들에게 트랜잭션과 보상트랜잭션을 명령하며 진행하는 방식
- 장점
- 현재 진행중인 트랜잭션 상태 추적 쉬움
- 단점
- 단일 장애지점이 존재
- 모든서비스가 결합됨
- 토스는 Orchestration Saga를 선택
- 클라이언트의 요청을 받는 환전 서버(Orchestrator 역할 가능)가 필요
- 진행중인 환전들의 상태를 관리/추척
- 환전 성공과 실패
- 정상적인 상황에서는 환전 서버가 원화계좌, 외화계좌에 요청하고 각 서비스들이 성공하는 케이스
- 그 외 실패 가능 케이스들이 존재
- 정상적인 실패
- 비정상적인 실패
- 정상적인 실패 처리
- 보상트랜잭션으로 성공한 서비스의 상태를 롤백
- 출금부터 처리
- Saga Pattern의 특징은 중간상태가 노출되는것
- 입금된 돈이 사용되면 취소가 어려움 (보상트랜잭션 수행의 어려움)
- 비정상적인 실패 처리
-
서버간 통신 방식
- 메시지방식은 메시지브로커 레벨에서 에러를 핸들링 및 재시도를 지원하기 때문에 대부분의 Saga는 메시징방식으로 구현됨
- 입금, 출금은 HTTP
- 입출금 결과를 알고넘어가야함 (동기)
- 유저는 환전이 즉시 완료되기를 기대함 (HTTP는 타임아웃 구현이 쉬움)
- 출금 취소는 Messaging (메시지 브로커에 에러핸들링을 위임)
- 출금 취소는 마지막 과정
- 유저가 기다릴 필요 없음(비동기)
- 출금 취소에 에러 핸들링을 하기 싫음, 결과적 정합성 보장만 되면 됨
- 에러 핸들링
- 출금/입금 요청에서 타임하웃 또는 실패를 응답받는경우
- 출금/입금 결과를 확인, 그 후속 (보상 트랜잭션) 처리 수행
- 결과확인에서 실패하는 경우
- 메지시를 지연해서 발행할 수 있는 Kafka Message Scheduler가 존재
- 지연을 통해 실패한 서비스가 회복할 시간을 줌
- 환전 서비스는 메지시를 컨슘해 보상트랜잭션 처리
- 지연 메시지 발행이 실패하는경우
- Batch를 통해 재처리
- Orchestration가 마지막 환전의 상태를 저장하고 있음
- 이후 프로세스를 배치를 통해 처리
- Batch를 통해 재처리
- 원화계좌가 출금취소 메시지를 받는것에 실패하는 경우
- Eventually Consistency: Consumer Dead Letter (CDL) 사용
- 원화 계좌는 메지시를 DL 서버로 전송
- DL 서버는 서비스 메시지 브로커로 출금 취소 메시지 발생
- Eventually Consistency: Consumer Dead Letter (CDL) 사용
- 출금/입금 요청에서 타임하웃 또는 실패를 응답받는경우
- Transactional Messaging
- Saga에서는 Local Transactional commit과 Message발행이 원자적으로 이루어져야함
- 입금 실패로 인한 환전 실패 처리와 출금 취소 메시지 발행은 항상 같이 이루어져야함
- 이를 위해 토스는 Producer Dead Letter를 사용
- 그 외 Outbox Pattern 등이 존재
- Saga에서는 Local Transactional commit과 Message발행이 원자적으로 이루어져야함
- 모니터링
- 결론 및 성과
- 손쉬운 확장 가능
- 회계
- 또 다른 Saga로 부족한돈 자동환전 결제
- Trade Off
- pros
- MSA 로의 전환, 기존 계정계 시스템이 가지는 문제 해결
- 계정계 시스템들과의 느슨한 결합, 확장 가능한 구조
- cons
- 트랜잭션 구현의 복잡도 증가
- pros
- 손쉬운 확장 가능