Redis를 사용하여 PHP에서 분산 잠금 구현

WBOY
풀어 주다: 2023-05-15 15:54:01
원래의
2514명이 탐색했습니다.

인터넷의 급속한 발전과 웹 사이트 방문의 급격한 증가로 인해 분산 시스템의 중요성이 점차 부각되고 있습니다. 분산 시스템에서는 동시성 동기화 및 데이터 일관성 문제가 필연적으로 수반됩니다. 동시성 동기화 문제를 해결하는 수단으로 분산 잠금은 점차 분산 시스템에서 널리 사용되었습니다. PHP에서는 Redis를 사용하여 이 기사에서 소개할 분산 잠금을 구현할 수 있습니다.

분산 잠금이란 무엇인가요?

분산 시스템에서는 여러 시스템이 동일한 작업을 함께 처리할 때 여러 시스템이 동시에 동일한 리소스에서 작동하는 것을 방지하기 위해 리소스를 잠가야 합니다. 분산 잠금은 분산 시스템에서 공유 리소스를 잠그는 메커니즘입니다. 분산 잠금은 다음 두 가지 요구 사항을 보장해야 합니다.

1. 상호 배타성: 언제든지 하나의 클라이언트만 잠금을 보유할 수 있습니다.

2. 재진입: 동일한 클라이언트가 여러 번 잠금을 획득할 수 있습니다.

분산 잠금을 구현하는 방법에는 데이터베이스 사용, 사육사 사용 등 여러 가지가 있습니다. 이 기사에서는 Redis를 사용하여 분산 잠금을 구현하는 방법을 소개합니다.

Redis가 구현하는 분산 잠금의 원리

Redis는 다중 데이터 구조를 지원하는 고성능 키-값 저장 시스템입니다. Redis에서는 SET 명령을 사용하여 분산 잠금을 구현할 수 있습니다. 구현 원칙은 다음과 같습니다.

1 클라이언트가 Redis에 SETNX 명령을 보냅니다.

2. Redis 서버는 수신된 SETNX 명령을 처리하고 지정된 키가 존재하는지 확인합니다. 존재하지 않는 경우 키 값이 클라이언트 ID로 설정되고 만료 시간이 설정됩니다. 존재하는 경우 실패가 직접 반환됩니다.

3. 클라이언트는 Redis가 반환한 결과를 받아 성공적으로 잠금을 획득했는지 확인합니다. 성공하면 해당 작업을 수행하고 일정 시간 동안 기다린 후 다시 요청을 보냅니다.

Redis를 사용하여 분산 잠금을 구현하는 단계

1. Redis에 연결

PHP에서 Redis에 연결하려면 PHPRedis 확장을 사용하므로 이를 사용하기 전에 설치해야 합니다. 구체적인 설치 방법은 공식 문서를 참고하세요.

2. 잠금 획득

다음과 같이 잠금을 획득하는 함수를 구현합니다.

protected function lock($lock_key, $expire_time = 5)
{
    $redis = new Redis();
    $redis->connect('localhost', 6379); // 连接Redis
    $micro_second = 1000000;
    $timeout = 10 * $micro_second; //等待锁超时时间

    while($timeout >= 0)
    {
        $microtime = microtime(true);
        $timeout -= $micro_second;
        $current_lock_time = $microtime + $expire_time + 1; //锁过期时间

        if($redis->setnx($lock_key, $current_lock_time)) //获取锁成功
        {
            $redis->expire($lock_key, $expire_time); //设置过期时间,防止死锁
            return $current_lock_time;
        }

        //检查锁是否过期
        $lock_time = $redis->get($lock_key);
        if($lock_time < $microtime)
        {
            $new_lock_time = $microtime + $expire_time + 1; //设置新的过期时间
            $old_lock_time = $redis->getset($lock_key, $new_lock_time); //获取旧的过期时间并设置新的过期时间
            if($old_lock_time < $microtime) //锁已经过期,获取锁成功
            {
                $redis->expire($lock_key, $expire_time); //设置过期时间,防止死锁
                return $new_lock_time;
            }
        }

        //等待一段时间后再次尝试获取锁
        usleep(10000); //等待10毫秒
    }

    return false;
}
로그인 후 복사

이 함수의 기능은 지정된 키의 잠금을 획득하는 것입니다. 획득에 성공하면 잠금 만료 시간을 반환합니다. ; 획득에 실패하면 false를 반환합니다.

3. 잠금 해제

잠금 획득 성공 후 작업 완료로 인한 것인지, 일정 시간 기다린 후 잠금 획득 실패로 인한 것인지 잠금을 해제해야 합니다. 다음과 같이 잠금을 해제하는 함수를 구현합니다.

protected function unlock($lock_key, $current_lock_time)
{
    $redis = new Redis();
    $redis->connect('localhost', 6379); // 连接Redis
    
    $lock_time = $redis->get($lock_key);
    if($lock_time == $current_lock_time) //判断是否为当前持有锁的客户端
        $redis->del($lock_key); //释放锁
}
로그인 후 복사

이 함수의 기능은 현재 잠금을 보유하고 있는 클라이언트만 잠금을 해제할 수 있다는 것입니다.

주의 사항

1. 잠금 만료 시간은 실제 상황에 따라 합리적으로 설정되어야 합니다. 잠금 만료 시간이 너무 짧으면 잠금이 만료되거나 잠금을 자주 얻을 수 없습니다. 잠금 만료 시간이 너무 길면 잠금 만료 시간이 너무 길어 시스템 성능에 영향을 줄 수 있습니다.

2. 만료 시간을 설정할 때 교착 상태를 방지하세요. 한 클라이언트가 잠금을 획득했지만 예기치 않은 종료 또는 충돌로 인해 잠금이 해제되지 않으면 다른 클라이언트가 잠금을 획득하는 데 영향을 미쳐 교착 상태 문제가 발생합니다.

3. 분산 잠금의 구현은 클라이언트의 고유 ID에 의존하기 때문에 여러 클라이언트는 서로 다른 ID를 사용해야 합니다. 그렇지 않으면 한 클라이언트가 다른 클라이언트의 잠금을 해제할 수 있습니다. PHP에서는 PHP_SESSION_ID 또는 IP 주소/프로세스 ID를 클라이언트의 고유 식별자로 사용할 수 있습니다.

결론

Redis를 사용하여 분산 잠금을 구현하는 것은 PHP에서 상대적으로 간단하고 실용적인 분산 잠금 솔루션입니다. 실제 적용에서는 교착 상태 문제를 방지하고 시스템의 안정성과 신뢰성을 보장하기 위해 실제 상황에 따라 잠금 만료 시간을 합리적으로 설정해야 합니다. 동시에 가능한 문제를 피하기 위해 클라이언트 고유 식별자의 고유성을 보장하는 데 주의를 기울여야 합니다.

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

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!