Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/hellozo0 step2 #29

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open

Feature/hellozo0 step2 #29

wants to merge 28 commits into from

Conversation

hellozo0
Copy link

구현사항

  1. 다른 계좌로의 송금
    • 송금시, 계좌에 잔액이 부족하다면 10,000단위로 충전 후 송금
    • 충전할 경우, 일일 충전 한도인 3,000,000을 넘는지 확인
  2. 0시 00분 기점으로 충전 한도 초기화

프로그래밍 요구사항

다른 계좌로의 송금

  1. 기존 [Step 1] Repeatable Read + Xlock에서 Read Commited + Xlock으로 모든 트랜잭션 변경
    • 100명이 동시에 송금을 할 경우가 있다고 했을 때, 락으로 인한 대기와 동시성 처리를 생각해 수정
  2. 한도 계산을 할때, Redis의 복구용으로 DB에 charge limit 컬럼 추가
    • redis에서 먼저 일일 한도 넘었는지 확인하는 로직은 그대로(트랜잭션 분리)
    • redis에서 일일 한도 안넘는거 확인하고, 값을 변경했다면 DB에 수정을 하도록 추가
  3. 트랜잭션 분리 과정
    • Redis Key-Value + @scheduled
    • <트랜잭션 1> 먼저 내 계좌에서 돈을 차감한다. 돈을 충전해야한다면 충전하고, 돈을 보낼 수 있다면 레디스에 <sender, receiver, 충전한금액 : 보내는 금액> 정보를 저장
    • <트랜잭션 2> @scheduled를 통해 3초 마다 레디스의 송금 데이터를 읽어서 receiver 계좌에 돈을 송금한다.
    • 만약 트랜잭션 2에서 실패했을 경우, 3회를 더 시도하고 그래도 실패할 경우 송금 최종 실패 롤백을 한다(보낸 이에게 돈 다시 송금)

0시 00분 충전 한도 초기화

  1. [Step1]에 이미 구현을 했어서 크게 달라지지는 않았지만 수정한 부분은 아래와 같다.
    • Batch로 Redis에 있는 키 값들의 데이터를 DB에서 조회해서 한번에 리셋
    • Redis에 있는 오늘치 데이터 다 삭제
    • 은행 저녁 점검 처럼 0시 부터는 10분간 redis를 사용 못하도록 lock

개선해야할 점

다른 계좌로의 송금

  1. 현재 스케줄러로 송금 데이터 쌓인것을 처리하는 부분이 비즈니스 로직상 맞지 않음
    • 현재 레디스 + 스케줄러로 데이터를 직렬화해서 송금 처리를 하는 부분이 하드코딩적인 로직이라고 생각
    • 메시지큐나 Redis Stream을 통해 이벤트를 인지해서 처리할 수 있도록 수정 해야된다고 생각
    • 또한 쓰레드풀을 사용해서 비동기 처리할 수 있도록 수정 (현재는 직렬화 되어 있어서 문제발생 가능성이 많음, 실패했을 때 해당 데이터를 3회 바로 수행 하는것 => 만약 비동기 처리 했으면 다른 송금 데이터 처리를 동시에 가능

0시 00분 충전 한도 초기화

  1. Redis 키 값으로 전체 조회하는 부분과 DB에 boolean 값을 둬서 오늘치 값을 다 초기화하는 방법 고민
    • 또는 transaction date를 기점으로 어제치를 다 초기화
    • 어떤 것이 성능상 이점이 있을지...크게 다르지 않을거라 생각하지만 더 쉬운방법을 고민중

- 은행계좌 번호 생성
- 로컬 캐시를 사용하려고 하였으나, 구현이 어려워 Redis를 통해 일일 한도 계산 로직 구현
- 캐시에서 한도 계산 조건에 부합한지 먼저 체크
- Balance를 추후에 수정
- 만약 balance transaction이 실패했을 경우 캐시 값을 rollback할 수 있도록 구현
- *redis lock을 구현한 부분은 추후 Scheduler commit때 설명 예정
- 12시가 되면 10분 동안 redis에 lock을 걸게 만드는 key-value를 생성하고 모든 데이터를 삭제한다
- 실제 일일한도 여부 파악하는 로직에서 lockKey가 reset인지 여부를 먼저 파악한다
- 실제 은행점검시간 존재하는 것에서 아이디어를 가져왔다
- Bank 번호 생성 Util화
- API 응답형태 변경
- Dto의 불필요한 유효성 검사 제거
- 트랜잭션 스크립트 패턴에서 도메인 모델 패턴으로 변경
- 격리레벨을  (100명 동시 이체를 위한 병목 줄이기 위해) Read Commited로 수정
- DB를 redis의 보조 DB로서 사용
- Batch로 DB 트랜잭션 N -> 1로 감소
- 보내는 사람의 계좌에서 돈을 차감하고 스케줄러를 통해 받는사람의 입금을 도와주는 로직으로 구현
- @scheduled + Redis 를 사용해서 순차적으로 처리하는 로직
- [문제점] 순차처리로 인한 송금 딜레이 문제, 비효율적인 작업 처리
- [개선방향] RedisStream이나 메시지큐 학습후 수정 예정
- 3초마다 송금 이력을 조회해서 송금해준다.
- 송금실패시, 롤백 ( 보낸 사람에게 돈 보내고, 일일한도와 같은 것들 다 되돌리기)
- 롤백을 실패했을 경우 사람이 처리하도록 넘기는 방식으로
@hellozo0 hellozo0 self-assigned this Feb 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant