1. 분산 시스템에서의 락의 필요성
컴퓨팅 시스템은 대부분 분산 시스템으로 구성되어 있습니다. 이러한 분산 시스템에서는 여러 대의 서버가 데이터를 공유하고 동시에 처리할 수 있습니다. 하지만 이러한 동시성은 데이터 일관성 문제를 발생시킬 수 있습니다. 동시에 여러 대의 서버에서 같은 데이터를 수정하면 어떤 서버가 마지막으로 수정한 내용을 사용할지 불명확해집니다. 이러한 문제를 해결하기 위해서는 락(Lock)이라는 메커니즘이 필요합니다.
락은 공유 자원에 대한 접근을 조절하는 메커니즘으로, 동시에 여러 스레드 또는 프로세스들이 공유 자원에 접근할 때 일관성을 보장합니다. 락을 사용하면 하나의 프로세스나 스레드만이 공유 자원에 접근하도록 보장할 수 있습니다. 다만, 분산 시스템에서는 락이 그보다 더 복잡해집니다.
이번에 DynamoDB에서 제공하는 분산 Lock 솔루션에 대해 알아보겠습니다.
2. DynamoDB가 제공하는 분산 Lock 솔루션
DynamoDB는 NoSQL 데이터베이스 서비스로, 분산 시스템에서 데이터 일관성과 가용성을 보장하는 매우 신뢰성 높은 서비스입니다. DynamoDB는 몇 가지 핵심 기능 중 하나로 분산 락(Distributed Locking)을 제공합니다.
DynamoDB의 분산 락은 락 전략으로 비관적 또는 낙관적 락 기법을 사용할 수 있습니다. 비관적 락 기법은 다른 클라이언트들이 락을 요청했을 때 해당 자원에 대해서 즉시 락을 걸고, 락이 걸려 있을 때는 다른 클라이언트들이 해당 자원에 대해서 접근할 수 없도록 합니다. 반면, 낙관적 락 기법은 자원에 대해서는 락을 걸지 않지만, 해당 자원을 수정할 때마다 업데이트 버전 번호를 생성하고, 업데이트 버전 번호가 일치하지 않으면 락을 실패하도록 하는 방식입니다.
DynamoDB의 락은 솔루션으로 SmartLock와 SmartDynamoDB가 있습니다. SmartLock는 DynamoDB의 레코드 락을 위한 라이브러리로, 비관적 락 기법을 사용하고 있습니다. SmartDynamoDB는 대용량 데이터 처리를 위한 기능과 함께 DynamoDB를 확장한 서비스로, 낙관적 락 기법을 사용하고 있습니다.
DynamoDB의 분산 락은 데이터베이스나 네트워크 레이턴시로 인한 문제에 대한 대응본으로서 안정적이며, 여러 기능이 함께 구현되어 있는 솔루션이기 때문에 사용자들에게 권장되는 방법 중 하나입니다.
3. DynamoDB의 락 매커니즘 이해하기
DynamoDB의 분산 락은 레코드 레벨에서 동작합니다. 레코드 락을 사용하면, 여러 클라이언트가 동시에 같은 레코드를 수정할 때 데이터의 일관성을 유지하게 됩니다.
DynamoDB의 레코드 락은 세 가지 측면에서 이해할 수 있습니다: Mode, Owner, Duration 입니다.
- Mode: DynamoDB의 락은 비관적 락과 낙관적 락 두 가지 모드로 지원됩니다. 비관적 락 모드는 레코드에 락이 걸려 있을 때, 다른 클라이언트는 해당 레코드에 접근할 수 없습니다. 락이 걸려 있는 동안에 다른 클라이언트는 대기해야 합니다. 낙관적 락 모드는 락을 걸지 않고, 레코드의 업데이트 버전 번호를 체크하여 일관성을 유지합니다.
- Owner: 락을 건 클라이언트의 ID를 Owner로 지정합니다. Owner는 락의 소유자이며, Owner가 락을 해제할 때 해당 레코드에 대한 다른 클라이언트의 접근 권한이 가능해집니다.
- Duration: 락의 지속 시간을 결정합니다. 락의 지속 시간은 락이 자동으로 해제되는 시간으로, 기본값은 300초(5분)입니다. 만약 클라이언트가 락을 해제하지 않은 채로 다운되면, 약간의 딜레이 이후에 자동으로 락이 해제됩니다.
DynamoDB의 레코드 락은 레코드의 값이 모두 업데이트 될 때 생성됩니다. 새로운 레코드를 추가하거나, 레코드의 부분적인 업데이트를 수행하는 경우에는 락이 걸리지 않습니다. 또한, DynamoDB의 락은 트랜잭션(Transaction)의 일부로 동작할 수 있으므로, 여러 데이터를 원자적으로 처리할 수 있는 기능을 제공합니다.
4. 락을 사용하는 예시 분석
DynamoDB의 레코드 락은 여러 클라이언트가 동시에 같은 레코드를 수정하는 동시 업데이트 상황을 방지할 수 있습니다. 이를 통해 데이터의 일관성이 유지됩니다. 레코드 락을 명시적으로 사용하는 가장 일반적인 시나리오 중 하나는 사용자 또는 애플리케이션에서 공유 자원을 사용하는 경우입니다.
예를 들어, A와 B라는 두 개의 클라이언트가 DynamoDB에서 같은 레코드에 접근하려고 합니다. 이 경우, 불일치가 일어날 수 있습니다. 예를 들어, A가 해당 레코드의 데이터를 읽은 후에 수정을 시도하지만 B가 먼저 수정을 완료하여 레코드가 갱신된 상태일 수도 있습니다. 이때 레코드 락을 사용하면, A와 B 모두가 레코드에 접근하고 데이터를 수정할 수 있지만, 락을 소유한 클라이언트가 완료하기 전까지는 다른 클라이언트가 레코드에 접근하지 못하도록 막습니다.
다음은 레코드 락을 사용하는 예시입니다.
import boto3
import time
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('my-table')
# 락 획득
response = table.update_item(
Key={'id': 'my-item-id'},
UpdateExpression='SET is_locked = :val',
ConditionExpression='attribute_not_exists(is_locked)',
ExpressionAttributeValues={':val': True})
if response['ResponseMetadata']['HTTPStatusCode'] != 200:
raise Exception('Unable to obtain lock')
# 락 획득 후 60초 동안 활동하기
try:
while True:
# 다른 작업 수행
...
# 락 갱신
response = table.update_item(
Key={'id': 'my-item-id'},
UpdateExpression='SET is_locked = :val',
ConditionExpression='is_locked = :val',
ExpressionAttributeValues={':val': True})
if response['ResponseMetadata']['HTTPStatusCode'] != 200:
raise Exception('Unable to update lock')
time.sleep(10)
finally:
# 락 해제
response = table.update_item(
Key={'id': 'my-item-id'},
UpdateExpression='REMOVE is_locked',
ConditionExpression='attribute_exists(is_locked)',
ReturnValues='ALL_OLD')
if response['ResponseMetadata']['HTTPStatusCode'] != 200:
raise Exception('Unable to release lock')
이 예시에서, 먼저 attribute_not_exists
를 사용하여 레코드에 락을 걸어 동시에 update 되지 않도록 하고, 다른 클라이언트가 동시에 락을 획득할 수 없도록 합니다. 이후, 일정 시간 실제 작업을 수행하면서 개체를 업데이트하고, 매번 is_locked
속성을 갱신하여 락을 유지합니다. 작업이 완료된 경우, REMOVE
를 사용하여 레코드에서 락을 해제합니다.
5. 락을 사용할 때 고려해야 할 사항
레코드 락을 사용할 때, 다음과 같은 몇 가지 고려사항이 있습니다.
1. 락의 유효 시간 설정
락은 각각의 클라이언트에서 설정한 현재 시간이 포함된 유효 시간으로 구성됩니다. 락이 유효한 시간이 지나면 자동으로 만료됩니다. 따라서 락이 오랫동안 유지될 경우, 클라이언트가 락을 보유하고 있음에도 불구하고 이 락이 만료될 수 있습니다. 이러한 경우, 락을 갱신하거나 새로운 락을 설정해야 합니다.
2. 락의 충돌 방지
락이 계속해서 존재하는 상황에서, 다른 클라이언트가 같은 레코드에 락을 설정하려고하면 충돌이 발생할 수 있습니다. 이러한 경우 is_locked
속성을 확인하여 다른 클라이언트에 의해 락이 이미 설정된 경우를 판단하고, 락 설정이 실패한다는 것을 알리는 방법을 사용할 수 있습니다. 이전 예시에서와 같이 ConditionExpression
을 사용하면 됩니다.
3. 동시성 제어
DynamoDB 락은 단일 레코드에 대한 동시 업데이트 간 충돌을 방지하기 위한 것입니다. 하지만, 분산된 환경에서 락을 사용하더라도, 여러 클라이언트에서 같은 레코드를 동시에 수정하는 것을 완전히 방지할 수 없습니다. 따라서, 클라이언트 간 동시성 문제를 방지하기 위한 적절한 워크플로우를 구현해야 합니다.
이러한 고려 사항 외에도, 디자인 아티팩트에서 락을 사용할지 여부를 통합하여 결정하는 것이 좋습니다. 락을 무분별하게 사용하면 성능에 영향을 미치며, 좋은 디자인 아티팩트는 클라이언트의 일관성과 효율성 모두를 고려해야 합니다.
6. DynamoDB를 이용한 락 활용 팁
다음은 DynamoDB를 이용하여 락을 설정할 때 유용하게 사용할 수 있는 몇 가지 팁입니다.
1. 락을 생성할 때 랜덤 문자열을 사용
락을 생성할 때, 랜덤 문자열을 사용하여 락의 이름으로 설정합니다. 이는 다른 클라이언트가 같은 락 이름으로 락을 설정하지 못하도록 보장합니다. 또한, 이를 통해 최초 락 설정 시도 이후 조금만 지연되더라도 두 번째 클라이언트가 동일한 락을 설정하는 것을 방지할 수 있습니다.
2. 데이터베이스에서 락 생성 및 갱신 시도 수 최적화
락을 생성하거나 갱신할 때 DynamoDB는 일련의 수행 단계를 거쳐야 합니다. 락 설정 및 갱신 수행 시, 이러한 단계의 수를 최적화하여 성능 향상을 도모할 수 있습니다.
결과적으로 코드 실행에 필요한 수행 단계 수가 줄어들면 락 생성 및 갱신 시도 수가 줄어들어 효율이 증대됩니다. 이러한 접근 방식은 무분별한 락 생성 및 갱신을 방지하고, 락을 사용하기 전에 다른 방법을 고려하는 것이 중요하다는 것을 상기시킵니다.
3. 락 예외 처리
DynamoDB 락 예외는 번거로울 수 있는 에러 중 하나입니다. 이러한 에러 발생 시, 최적의 다시 시도 로직을 구현해야 합니다. 재시도 로직이 최적화되지 않으면 락 해제를 몇 초간 지연시키는 이슈가 발생할 수 있습니다. 이를 방지하기 위해, 최적의 다시 시도 로직을 구현해야 합니다.
4. 락 갱신 쿼리를 최소화
락을 최대한 적게 갱신하는 것이 성능을 향상시키는 핵심적인 요소 중 하나입니다. 락 생성부터 갱신까지 모든 단계가 데이터베이스에서 부하를 일으키므로, 가능한한 자주 락 갱신쿼리를 최소화하도록 노력하여야 합니다.
계획적인 시간 간격으로 락을 갱신한다는 것도 가능합니다. 이렇게 하면 락을 갱신하지 않아도 최소한의 성능 영향을 받을 수 있습니다.
이러한 팁을 고려하여 락 관리 시스템을 적절히 조정하면, 락이 초당 몇천 회 이상 실행되는 분산 시스템에서도 효율적인 락 관리가 가능합니다.
7. 마치며
지금까지 DynamoDB의 분산 Lock에 대해서 알아보았습니다. 분산 시스템에서의 락의 필요성에 대해서 이해하고, DynamoDB가 제공하는 분산 Lock 솔루션의 강점과 매커니즘, 그리고 락을 사용할 때 고려해야 할 사항에 대해서 살펴보았습니다.
또한, 분산 시스템에서 락을 효율적으로 사용하기 위한 팁과 DynamoDB를 이용한 락 활용 방법에 대해 다루었습니다. 이러한 팁과 방법을 고려하면 믿을 수 있는 분산 락 관리 시스템을 구축하고 락 교착 상태를 예방할 수 있습니다.
분산 시스템에서 락은 오류를 방지하고 잠재적인 문제를 해결하는데 필수적인 요소 중 하나입니다. 이를 통해, 분산 시스템에서 안정성과 일관성을 유지할 수 있습니다.
이와 같이 DynamoDB로 분산 시스템에서 락을 관리하는 방법에 대해 살펴보았습니다. 이 글이 분산 시스템에서 락을 관리하는 방법에 대해 도움이 되기를 바랍니다.
이 글을 동영상에서 확인할 수 있듯이 OpenAI API를 이용해 구현한 서비스 G-ChatBot을 이용해서 작성하였습니다.
'ChatGPT > AWS Serverless' 카테고리의 다른 글
[AWS][DynamoDB] DynamoDB에서의 분삭 Lock 소개 - 2 (0) | 2023.06.10 |
---|---|
[OpenAI][ChatGPT] Session Manager with TypeScript and AWS DynamoDB (0) | 2023.04.17 |
[Serverless][DynamoDB] Simple Device Data Storage Application (0) | 2023.04.17 |
[Serverless][DynamoDB] Time Series Statistics Manager (0) | 2023.04.13 |
[Serverless][MySQL] Express Session Store (0) | 2023.04.12 |