1. 토미의 [인프라 개선하기 Part 2] 강의를 들었다.
최근 내가 살짝 공부했던 내용(파티셔닝, 샤딩)과
최근 팀 프로젝트를 위해 찾아보던 내용(역정규화, 커버링 인덱스, 페이징 처리) 등이 나와서 반가웠다!
공부를 올바른 방향(?)으로 하고 있는 것 같아 조금 뿌듯했다.
쇼핑몰 아키텍처를 예시로 인프라를 개선해나가는 과정을 보여주셨는데 너무너무 재밌었다!
인프라는 참 정답도 없고 무궁무진한 것 같아서 신기하고 재밌다.
얼른 대용량 데이터를 다루는 회사에 입사해서 재밌는걸 많이 해보고 싶다.
2. 동시성 이슈 관련 글들을 읽었다.
동시성 문제의 근본적인 해결 방법은 가변데이터에 순차적으로 접근할 수 있는 방법을 구상하는 것
📍 일반 변수에 대한 동시성 문제 해결 방법
synchronized : 해당 블럭의 액세스를 동기화 (동시에 하나의 스레드만 접근)
volatile : CPU 메모리 영역에 캐싱 된 값이 아니라 항상 최신의 값을 가지도록 메인 메모리 영역에서 값을 참조하도록
concurrent 패키지 <- 얘가 성능상 제일 낫다
📍 메서드에 synchronized 적용
- 인스턴스 단위로 lock
- @Transactional과 함께 사용될 경우 문제
- 트랜잭션(@Transactional)과 동기화(synchronized)는 서로 다른 개념
- synchronized : 메서드가 한 번에 하나의 스레드에서만 실행할 수 있도록 Locking
- 트랜잭션 : 하나의 트랜잭션이 commit되기 전, 다른 트랜잭션이 시작할 수 있다.
- 스프링의 @Transactional은 프록시 방식으로 동작
- tx begin -> 로직 실행 -> tx commit
- 즉, synchronized 블럭은 벗어났으나 tx commit 전에 다른 스레드에서 해당 메소드가 시작될 수 있다.
- (tx begin, tx commit은 synchronized의 영향을 받지 않는다)
- t1 commit 전 t2가 메소드를 시작할 수 있다.
- 단점
- 한 스레드가 메서드 작업을 완료할 때 까지 다른 스레드들은 대기 -> 성능 저하
- 하나의 프로세스 안에서만 보장 -> 서버가 여러대인 분산 환경에서는 데이터의 정합성을 보장할 수 없다.
📍 DB를 이용한 Lock
- 낙관적 락 (non-blocking 방식)
- 트랜잭션 간 충돌이 일어나지 않을거라 예상
- @Version + @Lock(LockModeType.OPTIMISTIC)
- 장
- 별도의 Lock이 없기 때문에 성능상 이점
- 단
- 실패했을 시(버전 충돌이 있어났을 경우) 로직을 개발자가 직접 만들어야함
즉, 애플리케이션단에서 try-catch등의 로직 짜줘야함 (ex. 재시도) - 충돌이 빈번히 일어나면 성능상 손해 (계속 충돌나서 재시도해야함)
- 실패했을 시(버전 충돌이 있어났을 경우) 로직을 개발자가 직접 만들어야함
- 비관적 락 (blocking 방식)
- 트랜잭션 간 충돌이 일어날 것이라 예상
- S-Lock
- @Lock(LockModeType.PESSIMISTIC_READ)
- X-Lock
- @Lock(LockModeType.PESSIMISTIC_WRITE)
- 단일 DB 환경에만 적용 가능 (분산 DB 환경에서는 동시성 제어의 효력을 잃는다)
- 많은 대기 시간이 발생한다
(한 트랜잭션이 완료되기 전까지 다른 트랜잭션들은 대기상태에 빠진다.
동시에 많은 요청이 들어왔을 때, 사실상 하나의 요청씩만 작업할 수 있으므로 요청의 수가 많아지면 대기 시간이 길어진다) - 데드락 위험
cf) 데드락 : 말그대로 그냥 교착 상태 -> 동시성 이슈와 직접적인 연관은 없다
3. 펀잇 1.2버전 배포
펀잇 서비스 인스타 광고를 위해
카드뉴스를 만들어서 쫙 업로드했다.
https://instagram.com/fun__eat?igshid=MzRlODBiNWFlZA==
그리고 홈화면을 리뉴얼하여 1.2버전으로 배포했다!
https://funeat.site