-
동시성 해결에 관해글또 2022. 8. 21. 17:48
해당 글은 인프런 강의를 토대로 작성되었습니다.
우리의 애플리케이션은 공유 자원에 접근하여 작업을 할 때 실행결과가 예상과 달라질 수 있습니다.
이런 문제를 레이스 컨디션이라고 합니다.
이를 해결하기 위해서 몇 가지 방법이 제시됩니다.
1. JVM 언어에서 제공되는 synchronized 사용
2. DB에서의 Lock 사용
3. Redis의 Lock 사용1. JVM 언어에서 제공되는 synchronized 사용
애플리케이션 레벨에서 제어를 할 수 있습니다.
jvm언어에서는 synchronized라는 키워드를 제공합니다.
이는 공유 자원에 대해 하나의 스레드만 접근할 수 있도록 합니다.이는 문제점이 있습니다.
1. 다중 애플리케이션의 경우에는 synchronized가 의미가 없습니다. 각자의 애플리케이션 레벨에서 접근을 막는 것이기에 조회를 동시에 진행한다면 결과는 원하는 것이 아닐 겁니다.
2. Spring에서는 작업 단위를 잡기 위해 @transactional이라는 어노테이션을 제공합니다. 이는 proxy를 만들어 동작하도록 되어있습니다.
데코레이터 패턴으로 구현되어 있기에 하나의 스레드가 decrease 메서드를 종료시키고 commit 전에 다른 스레드가 decrease메서드를 실행시켜 commit전의 정보를 DB에서 가져온다면 문제가 될 수 있습니다.2. DB에서의 Lock 사용
비관적 lock과 낙관적 lock을 사용할 수 있습니다.
+ (mysql) 이름을 가진 lock을 직접 사용. 참고1. 비관적 lock은 row 또는 table에 lock을 걸어 데이터에 대한 접근을 제어합니다.
이는 충돌이 잦거나 중요한 정보 일 경우 사용할 수 있습니다. 단점은 데드락의 위험과 성능 저하입니다.
select for update 등으로 구현할 수 있습니다.* Exclusive Lock또는Shared Lock을 거는 방법입니다.
2. 낙관적 lock은 동기화를 원하는 테이블에 하나의 칼럼(ex. version)을 둬서 체크를 하는 방식입니다.
select시와 update시에 version이 동일하지 않다면 update를 하지 않을 수 있습니다.
위의 둘은 모두 spring jpa에서 간단하게 구현이 가능하도록 되어 있습니다.낙관적 lock의 경우는 version이 다를 경우 update가 되지 않기에 이를 위한 방어 로직을 개발자가 구현해야 할 수 있습니다.
3.named lockmysql에는 lock을 획득할 수 있는 function이 존재합니다.
lock의 이름을 특정해 lock을 획득하고 트랜젝션을 동작하게 한 후 lock을 반환하는 형태로 구현할 수 있습니다.
lock용 dataSource를 만들어 커넥션을 관리할 수 있습니다.분산 락으로 사용할 수 있습니다.
세션을 가지고 락이 걸려있는지 확인등을 해야하므로 DB에 부하가 있음
3. Redis 사용
다른 관점으로 벗어나 레디스라는 것을 통해 관리 동시성을 제어할 수 있습니다.
분산 락을 이용
분산 락은 여러 노드끼리 관심사의 정합성을 맞추는 방법 중 하나이며 어딘가에 락을 저장해야합니다. 그 어딘가를 redis를 사용하는 것 입니다.
다중 DB환경에서 사용하며 단일 DB환경에서도 사용은 가능합니다.
redis는 key value 값 구조의 비정형 데이터를 관리하는 인메모리 DBMS입니다.
named lock과 다른 점은 레디스를 사용한다는 것과 세션 관리에 신경을 쓰지 않는다는 것입니다.
둘 다 구조는 named lock과 비슷합니다.
key와 value를 통해 lock을 구현하고 획득, 삭제 등으로 구현합니다.
1. lettuce lock
spin lock을 사용하는 방식입니다.
spin lock은 lock을 획득할 때까지 계속해서 lock 획득을 시도합니다. 그렇기에 레디스에 부하가 갈 수 있습니다.
개발자가 lock획득, unlock을 구현해야 합니다.
2. redisson lock
pub, sub 형태로 구현되어 있습니다. lock을 해제하게 되면 sub들에게 알림을 줘, sub들이 lock획득을 시도할 수 있게 됩니다.
이는 따로 라이브러리가 존재하여 손쉽게 구현할 수 있습니다. 재시도 또한 라이브러리에서 자체적으로 구현되어 있습니다.
단점은 leaseTime을 적게 잡으면 lock이 해제될 수 있습니다.실무에서는 재시도가 필요하지 않음 -> lettuce
재시도 필요 -> redisson
을 활용한다고 합니다.
Redis의 경우는 따로 구축해야 하고 관리 포인트가 증가한다는 단점이 있습니다만 성능은 인메모리이기에 mysql의 lock을 사용했을 때 보다 좋습니다.
mysql의 lock은 별도의 구축비용이 들지 않기에 좋은 선택지가 될 수 있습니다.'글또' 카테고리의 다른 글
인프콘을 보고 (0) 2022.09.23 레거시 코드를 대하는 법 (0) 2022.09.03 log4j2 (0) 2022.08.07 토스 slash 22 를 보고 (0) 2022.07.25 jvm 시간대 (0) 2022.07.18