동시성 문제 발생
Basecode 성능 테스트 결과 분석
동시성 문제로 인해 쿠폰 테이블의 발급 수량과 쿠폰 이슈 테이블의 발급 수량이 일치하지 않는 문제가 발생했다. 이는 다수의 사용자가 동시에 동일한 쿠폰을 요청할 때 발생하는 데이터 불일치 문제로, 이를 해결하기 위해 다양한 Lock(락) 메커니즘을 적용해야 한다.
coupon 테이블 | coupon-issues 테이블 | |
Basecode | 1,653 | 14,932 |
락을 적용하는 방법은 크게 Java 애플리케이션 레벨과 데이터베이스 또는 분산 시스템 레벨로 나눌 수 있다. 상황에 따라 적합한 방법을 선택하여 동시성 문제를 해결한다.
•
Java 애플리케이션 레벨 Lock
•
데이터베이스 레벨 Lock
•
분산 시스템 레벨 Lock
Java 애플케이션 레벨 Lock
애플리케이션 코드 내에서 동시 접근을 제어하는 방식이다.
방법 | 설명 | 적용 시 장점 | 단점 |
synchronized 키워드 | 메서드 또는 코드 블록에 동기화를 걸어 한 번에 하나의 스레드만 접근할 수 있게 제한한다. | 구현이 간단하고 JVM의 스레드 관리로 안정적이다. | 분산 환경에서는 효과적이지 않다. |
ReentrantLock | 자바에서 제공하는 Lock 객체로 더 세밀하게 락을 제어할 수 있다. 예: 락 타임아웃 설정 가능. | tryLock()을 통해 실패 시 타임아웃 처리 가능, 유연한 락 관리. | 사용자가 직접 unlock() 처리를 해야 한다. |
Atomic 변수 사용 | AtomicInteger, AtomicLong 등 원자적 연산을 제공하는 클래스를 사용하여 동시 접근 문제를 해결한다. | 간단한 값의 갱신 시 적합하며 성능이 빠르다. | 복잡한 로직에는 사용이 어려움. |
데이터 베이스 레벨 Lock
데이터베이스의 동시 접근 제어를 통해 데이터 불일치를 방지한다.
방법 | 설명 | 적용 시 장점 | 단점 |
낙관적 락
(Optimistic Lock) | 데이터 읽기 후 수정 시점에 버전 번호를 비교하여 충돌 여부를 확인한다. | 트랜잭션이 가볍고, 대부분 충돌이 적은 경우에 성능이 우수하다. | 충돌이 많을 경우 지속적인 실패가 발생할 수 있다. |
비관적 락 (Pessimistic Lock) | SELECT FOR UPDATE를 사용하여 데이터를 읽는 동안 다른 트랜잭션이 접근하지 못하도록 막는다. | 동시 수정 시점에 충돌을 확실하게 방지할 수 있다. | 락 유지 시간이 길어지면 성능 저하가 발생한다. |
행 단위 락 | 특정 행에만 락을 걸어 나머지 데이터의 접근은 허용한다. | 최소한의 데이터 락으로 병렬 처리 성능이 보장된다. | 복잡한 쿼리 구조 시 관리가 어려울 수 있다. |
분산 시스템 레벨 Lock
다수의 서버에서 동작하는 시스템에 대한 동시성 제어를 위한 방법이다.
방법 | 설명 | 적용 시 장점 | 단점 |
Redis 분산 락 | Redis를 이용해 SET NX 명령어를 사용하여 분산 락을 구현한다. | 빠르고 구현이 간단하며 Redis의 성능을 활용할 수 있다. | 만료 시간 설정을 주의해야 한다. |
Zookeeper 분산 락 | Zookeeper의 ZNode를 활용하여 동기화된 분산 락을 제공한다. | 트랜잭션 보장 및 강력한 동기화가 가능하다. | 설정 및 유지 보수가 복잡하다. |
ETCD/Consul 분산 락 | Key-Value 스토어를 기반으로 분산 시스템 락을 구현한다. | 데이터 일관성이 보장되며 분산 환경에서 안정적이다. | 추가 인프라 구성이 필요하다. |
결론
동시성 문제를 해결하기 위해 Java Synchronized 키워드, Redis 분산 락, 그리고 MySQL 비관적 락(SELECT FOR UPDATE)을 각각 적용한 후, 성능 테스트를 통해 성능과 안정성을 비교하고 최적의 방법을 선택한다.
Related Posts
Search