Q. 인상깊었던 주제는 무엇이었나요?
분산락과 캐시 전략중 어떤 주제가 더 인상깊었나요?
항해를 하기전 레디스를 사용해왔을때는 JWT 토큰정도로만 해왔습니다. Key value 기반 NoSQL 데이터베이스인 레디스가 단순히 캐싱의 역할을 하지 않고 Lock으로서의 역할을 할 수 있다는걸 이번과제를 통해 새로알게됐습니다. 또한 읽기와 쓰기에서의 캐싱전략이 여러가지가 있다는걸 처음알게됐습니다.
해당 개념을 통해 어떤 구조적/성능적 문제 해결을 가능성을 느꼈나요?
아직까지는 과제를 수행해보면서 어느점이 문제인지, 그에 대한 해결은 무엇인지에 대한 답변이 명확하지 않았습니다. 그래도 떠오르는 한가지는 캐싱쪽에서는 트랜잭션을 접근하기전에 캐시저장소(redis)에서 캐시히트가되면 빠른 응답을 해줄 수 있다는 점입니다.
Q. Race condition, Deadlock, Cache Stampede 등 방어할 포인트는 어떻게 설계하나요?
- Race condition & Deadlock
분산락을 도입하기전에 동시에 좌석예약을 할경우에는 낙관적락을 사용하여 빠른 실패를 나타내어 해결을했습니다. 그러므로 낙관적락은 논리적락으로써 Race condition, DeadLock 문제는 자연스레 해결이 됐습니다.
포인트 충전/사용 의 경우에는 배타락을 사용하였습니다. 동시요청이 들어와도 포인트라는 공유자원에 대한 데이터의 정합성을 우선으로 하였기때문에 비관적락이자 물리적락인 x-lock을 사용했습니다. 유저포인트라는 공유자원을 동시에 요청할때 락을 획득하지 않은 다른 트랜잭션들은 읽기/쓰기 접근을 하지못하도록 막습니다.
솔직히 기존의 락으로도 Race condition이나 dead-lock을 막을 수 있다고 생각합니다.
- Cache stampede
이에 대한 방어포인트는 데이터의 변경이 자주 일어나는지? 데이터의 변경이 드문지를 파악해야될거 같다고 생각합니다.
Q. 여러 캐싱방식과 락 구현방법중 어떤것을 왜 선택했는지 설명해주세요.
- 분산락 구현 계획과 그이유
| 사용 기능 | 사용 분산락 | 사유 | TTL |
|---|---|---|---|
| 좌석 임시예약 | 심플락 | 재시도횟수가 필요없으며, 동일한좌석에 대해 동시접근할때 1명을 제외한 나머지는 빠른실패를 비롯한 즉각적인 응답을 나타내야하기때문입니다. | 5분 |
| 포인트 사용 & 충전 | 스핀락 | 포인트(공유자원)에 대한 접근을 배타락으로 보호하여 동시요청이 오더라도 데이터정합성을 지키기위해서 동시에 충전/사용이 처리가 됩니다. 동시에 접근을 차단해주며, 다시 시도하여 순차적으로 처리하여 데이터의 정합성까지 지키기위해서 스핀락을 사용하기로 했습니다. 락을 점유할 수 있는 최대시간은 5초이며, 락 획득을 위해 다른 스레드가 기다릴 수 있는 최대시간은 5초입니다. 락을 얻기위해 다시 시도를 하기위한 시간은 100ms 로 설정했습니다. | 5초 |
- 캐싱방식 구현 계획과 그이유
| 사용 기능 | 선택전략 | 사유 | TTL |
|---|---|---|---|
| 콘서트목록 | 읽기전략 | 현재를 기준으로 예약가능한 목록리스트를 불러오기위함입니다. | 60분 |
| 콘서트일정 목록 | 읽기전략 | 현재를 기준으로 예약가능한 콘서트 일정목록을 나타내며 concertSeat, concert테이블을 조인하기때문입니다. | 30분 |
| 콘서트좌석목록 | 읽기전략 | 좌석상태(예약확정, 임시예약, 예약가능)를 확인하기 위함입니다. 상시변경가능성이 높기때문에 TTL고려가 필요 | 5분 |
| 토큰발급 | 쓰기전략 | 토큰상태 상관없이 토큰의 유효시간은 5분이기때문에 토큰의 유효성을 나타내기위함입니다 | 5분 |
| 좌석 임시예약 | 쓰기전략 | 좌석상태가 변경되기때문에 캐시저장소와 데이터베이스에 저장된 데이터가 일치하도록 정합성을 지켜야합니다. 예를들어 데이터의 정합성이 어긋나버리면 좌석이 이미 임시예약상태인데 클라이언트입장에서는 예약가능하다고하면 UX상에서도 불편함을 초래할 수 있기때문입니다. | 5분 |
| 좌석 임시예약 취소 | 쓰기 전략 | 임시예약의 유효시간(5분)이 지났기때문에 스케줄러에 의해 취소처리가됩니다. 취소처리된 좌석은 다시 예약가능한상태이므로, 데이터의 정합성을 위해서 캐시저장소와 데이터베이스에서도 즉시 반영을 해야합니다. | 5분 |
Q. 구현중 어려웠던 점과 고민했던 선택지는 무엇이었나요?
이번과제의 아무래도 분산락과 캐싱전략에 대한 이해. 즉 과제의 요구사항를 이해하는것이 어려웠던것같습니다. 제겐 처음인거 같았고 낯설었습니다. 익숙해지는데 시간이 많이 필요했습니다.
콘서트시나리오에서는 어느기능에서 어떤 분산락을 써야될지, 어느기능에서 캐싱이 필요한지를 파악하는 것과 각 분산락 기법과 각 캐싱전략에 대한 이해가 필요했습니다. 분산락과 캐싱과의 관계가 있는지 모르는게 투성이었습니다.
임시예약과 예약취소는 좌석의 상태를 변경이 일어나므로, write-through를 전략으로 콘서트좌석목록을 캐싱하는 방안으로 했습니다. 콘서트좌석목록은 데이터의 변경이 자주일어나서 데이터의 정합성을 지키는게 우선이라고 생각했습니다. write-through 전략의 이론처럼 캐시저장소와 데이터베이스의 동기화시켜 데이터의 정합성을 지키는 쪽으로 구현했습니다.
Q. 이번주차를 통해 얻은 인사이트는 무엇이었나요?
이번주차를 통해 얻은 인사이트와 다음에 적용할 포인트가 무엇이며, 이번학습을 통해서 성능/동시성 에 대한 어떤 관점이 생겼을까요?
제가 얻은 인사이트는
- 첫번째로는 분산락은 트랜잭션보다 먼저 수행되어야하며, 트랜잭션이 종료후에 락을 해제하므로 트랜잭션보다 나중에 끝난다.
- 락획득 -> 트랜잭션시작 -> 수행 -> 트랜잭션종료 -> 락해제
- 분산락은 방어선 역할일뿐, 기존의 RDBMS의 비관적락과 논리락인 낙관적락 등의 대체제는 아니다.
- 캐싱에는 읽기 전략만 있는게 아니라 쓰기전략도 존재하며, 쓰기전략에는
앞으로 실무프로젝트나 이후 과제에서 “이 전략을 사용해보고싶다” 포인트가 있을까요?
기존의 락으로 해결하기 어렵고, 분산락만이 해결될 수 있는 상황은 어떤 상황인지에 대해 나만의 언어로 정리해보고 싶습니다.
프로젝트라기보다는 이 주제에 대해서 조금더 부딪혀보고 조금이라도 더 이해해보고 싶다는 생각이 들었습니다.
왜 락획득을 트랜잭션접근 이전에 해야될까? 이 순서가 지켜지지 않을때 왜 데이터의 정합성이 깨져버릴까? 에 대한 구체적인 예시를 근거로 만들어내서 나만의 언어로 정리해보고싶습니다.
이번주차에 연관된 기술이론을 바탕으로 주먹구구식으로 과제에 접목해서 임해왔지만, 성능적인 측면을 개선해보는 조금 더 나아가서 생각해보고 깊게 고민해보고 싶습니다.
캐싱전략들중 여러개의 전략들이 있는데 직접 구현해보고 그 차이점이 무엇인지 나만의 언어로 정리해보고싶습니다.