>데이터 베이스 >Redis >Redis의 분산 잠금 구현에 대한 자세한 설명

Redis의 분산 잠금 구현에 대한 자세한 설명

WBOY
WBOY원래의
2023-06-21 11:02:381159검색

모바일 인터넷의 급속한 발전과 데이터 양의 폭발적인 증가로 인해 분산 시스템이 점점 더 대중화되고 있습니다. 분산 시스템에서는 동시 작업 문제가 점점 더 두드러지고 있습니다. 여러 스레드가 동시에 공유 리소스를 요청하는 경우 데이터 일관성을 보장하기 위해 이러한 리소스를 잠가야 합니다. 분산 잠금은 분산 시스템에서 동시 작업을 구현하는 효과적인 솔루션 중 하나입니다. 이 기사에서는 Redis를 사용하여 분산 잠금을 구현하는 방법을 자세히 소개합니다.

  1. Redis 기본

Redis는 분산 시스템에서 널리 사용되는 메모리 기반 키-값 저장 시스템입니다. 고성능 NoSQL 데이터베이스인 Redis는 효율적인 읽기 및 쓰기 성능과 풍부한 데이터 구조로 많은 주목을 받았습니다. Redis는 여러 머신을 기반으로 분산 스토리지를 구현할 수 있으며 다음 데이터 구조를 지원합니다.

  • String
  • Hash
  • List
  • Set
  • Ordered set( sorted set)

Redis의 작업은 이러한 데이터 구조를 기반으로 합니다. 분산 잠금을 구현하려면 Redis의 기능인 SETNX(존재하지 않는 경우 SET)를 사용해야 합니다. 즉, 지정된 키가 존재하지 않는 경우 키 값을 설정할 수 있습니다. 키가 이미 존재하는 경우 SETNX 작업은 실패를 반환합니다.

  1. 분산 잠금 구현 아이디어

분산 잠금을 구현하려면 먼저 목표를 명확히 해야 합니다.

  • 분산 환경에서는 여러 스레드가 동시에 동일한 리소스를 요청할 때 다음이 필요합니다. 하나의 스레드만 잠금을 얻을 수 있도록 합니다.
  • 스레드가 잠금을 획득한 경우 다른 스레드는 잠금이 해제될 때까지 기다려야 합니다.

위 목표를 달성하기 위해 다음 아이디어를 채택할 수 있습니다.

  • Redis의 SETNX 명령을 사용하여 잠금 식별용 새 키를 만듭니다.
  • SETNX 명령이 성공적으로 반환되면 현재 스레드가 잠금을 획득했음을 의미합니다.
  • 교착 상태를 방지하려면 키 만료 시간을 설정하세요.
  • 스레드가 작업을 완료하면 잠금이 해제됩니다. 즉, 키가 삭제됩니다.
  1. 구현 코드 예시

먼저 Redis 연결을 생성합니다:

import redis

conn = redis.Redis(host='localhost', port=6379, db=0)

그런 다음 잠금 획득 및 해제 기능을 정의합니다:

def acquire_lock(conn, lockname, acquire_timeout=10, lock_timeout=10):
    identifier = str(uuid.uuid4())
    lockname = "lock:" + lockname
    end = time.time() + acquire_timeout
    while time.time() < end:
        if conn.setnx(lockname, identifier):
            conn.expire(lockname, lock_timeout)
            return identifier
        elif not conn.ttl(lockname):
            conn.expire(lockname, lock_timeout)
        time.sleep(0.001)
    return False

def release_lock(conn, lockname, identifier):
    pipe = conn.pipeline(True)
    lockname = "lock:" + lockname
    while True:
        try:
            pipe.watch(lockname)
            if pipe.get(lockname) == identifier:
                pipe.multi()
                pipe.delete(lockname)
                pipe.execute()
                return True
            pipe.unwatch()
            break
        except redis.exceptions.WatchError:
            pass
    return False

그 중 acquire_lock 함수를 사용하여 잠금을 획득하며, 매개변수 설명은 다음과 같습니다.

  • conn: Redis 연결입니다.
  • lockname: 자물쇠의 이름입니다.
  • acquire_timeout: 잠금 획득 시 제한 시간, 기본값은 10초입니다.
  • lock_timeout: 잠금 만료 시간, 기본값은 10초입니다.

이 함수는 먼저 임의의 식별자를 생성한 다음 0.001초마다 잠금 획득을 시도하고 만료 시간을 설정합니다. 지정된 제한 시간 내에 잠금이 획득되지 않으면 False가 반환됩니다.

release_lock 함수는 잠금을 해제하는 데 사용됩니다. 매개변수 설명은 다음과 같습니다.

  • conn: Redis 연결입니다.
  • lockname: 자물쇠의 이름입니다.
  • identifier: 잠금을 획득할 때 반환되는 식별자입니다.

이 함수는 먼저 WATCH 명령을 사용하여 잠금을 모니터링합니다. 잠금 값이 식별자와 동일하면 MULTI 명령을 사용하여 잠금을 삭제하고 작업을 수행합니다. 그렇지 않으면 모니터링을 종료하고 False를 반환합니다.

마지막으로 acquire_lock 및 release_lock 함수를 사용하여 분산 잠금 기능을 구현합니다. 샘플 코드는 다음과 같습니다.

import time
import uuid

def do_task():
    print("Task started...")
    time.sleep(5)
    print("Task finished")

def main():
    lockname = "mylock"
    identifier = acquire_lock(conn, lockname)
    if not identifier:
        print("Failed to obtain lock")
        return
    try:
        do_task()
    finally:
        release_lock(conn, lockname, identifier)

if __name__ == '__main__':
    main()

이 샘플 코드에서는 acquire_lock 함수를 사용하여 잠금을 획득하고, release_lock 함수를 호출하여 작업 실행 후 잠금을 해제합니다.

  1. 요약

분산 잠금은 분산 시스템에서 널리 사용되는 기술로, 동시 작업 시 데이터 일관성 문제를 효과적으로 해결할 수 있습니다. 본 글에서는 Redis를 사용하여 분산 잠금을 구현하는 방법을 자세히 소개합니다. Redis의 SETNX 명령과 만료 시간 설정은 물론 WATCH 및 MULTI 명령을 사용하여 분산 잠금 기능을 구현할 수 있습니다.

위 내용은 Redis의 분산 잠금 구현에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.