본문 바로가기
👨‍💻 프로그래밍/Architecture

🔒 분산 Architecture에서 Redlock으로 Lock 걸기

by 개발자 진개미 2023. 9. 28.
반응형

분산 Architecture에서 Lock 걸기의 어려움

Monolithic Architecture에서도 성능을 고려하면 Lock 걸기가 복잡했습니다. 여러 Transaction Level을 고려하고, 재시도 매커니즘을 고안하고, Deadlock 상황에서 어떻게 해야할지 고려하고..

근데 여기에 더해 MSA 같은 분산 Architecture에서 Lock을 걸어야 한다면 어떨까요? 성능을 더욱 고려해야 하고, Transaction 거는 것도 훨씬 복잡하고, Deadlock은 밥 먹듯이 있지 않을까요?


Redis Instance가 1개일 경우

만약 Redis 1개를 공유하면 Lock을 구현하는건 비교적 간단합니다.

Lock 별 고유한 Key를 정의한 후, setNX를 사용해서 있을 경우 set하고, 없을 경우 get하면 됩니다. 있을 경우 기다렸다 다시 시도하고, 혹시 Lock을 relase 못할 경우를 대비해서 timeout까지 두면 딱히 큰 문제는 없습니다.

// Spring의 경우
if (redisTemplate
	.opsForValue()
	.setIfAbsent(KEY, VALUE, Duration.ofSeconds(SECONDS))
) {
	// Lock을 획득한 경우
}

 

추가로 고려한다면 Lock을 획득할 때 Value에 Lock을 거는 쪽만 아는 고유값을 넣어두면 Multi Thread 환경에서의 안정성도 보장할 수 있겠네요.


Redis Instance가 여러개일 경우 Redlock 사용하기

하지만 Redis 1개를 사용하면 Redis가 SOP (단일장애지점)이 생기기 때문에, 보통 Redis Cluster를 사용해 Redis를 복재하거나 Sharding을 진행합니다. 

이 경우, 문제가 복잡해 집니다. 일단 각 Redis Instance간 Replication Delay가 있기 때문에 setNx로 Lock을 획득해도 Replication Delay를 기다려야 합니다. 하지만 Replication Delay를 얼마나 기다려야 할지 모르고, 없을지도 모르는 Replication Delay 때문에 시간이 상당히 지연됩니다.

이럴때는 Redlock 알고리즘을 사용하면 됩니다. Redlock에서는 다수결의 Redis Instance에서 Lock을 획득하면 Lock을 획득한 걸로 보는 알고리즘입니다.


추가로 고려해야 할 점

Lock을 획득했는데 Release 하기 전에 Down 됐을 경우

위와 비슷하게 Timeout을 주면 해결됩니다. 

 

2개의 instance가 비슷하게 다수결의 Lock표를 얻었을 경우

최초의 Timestamp를 비교해서 먼저 얻은 쪽에 우선순위를 두는 등의 방법으로 해결 가능합니다.

 

다수결의 Lock표를 애초에 획득할 수 없는 경우

이 경우 정합성이 얼마나 중요하냐에 따라 다르겠지만 Log를 잘 남겨두고 Lock 획득 처리하고 나중에 Batch를 돌릴 수도 있고, 특정 timeout 이상 지나면 Reset해서 처음부터 다시 시작하게 할 수도 있습니다.


추가로 알아보기

 

Redlock | Redis

Learn about Redlock, a distributed lock manager that allows multiple processes to coordinate access to shared resources in a distributed environment , and discover best practices for safe and effective use.

redis.com


 

반응형