>데이터 베이스 >Redis >Redis는 어떻게 재고 동시성 문제를 해결하고 수량 제어를 달성합니까?

Redis는 어떻게 재고 동시성 문제를 해결하고 수량 제어를 달성합니까?

PHPz
PHPz앞으로
2023-05-29 09:52:20964검색

Redis는 단일 프로세스이며 차단 유형입니다. 동시에 하나의 요청만 처리할 수 있으며 후속 요청은 대기해야 합니다.

장점: 단일 프로세스이므로 동시성 문제를 처리할 필요가 없어 시스템 복잡성이 줄어듭니다.

단점: 대용량 개체(100kb 이상)를 캐싱하는 데 적합하지 않습니다.

이유: Redis는 단일 코어인 경우 Memcached는 여러 코어를 사용할 수 있으므로 평균적으로 Redis는 각 코어에 작은 데이터를 저장할 때 Memcached보다 더 높은 성능을 제공합니다.

100,000개가 넘는 데이터의 경우 Memcached의 성능이 Redis보다 높습니다. Redis도 빅데이터 저장 성능에 최적화되어 있지만 여전히 Memcached보다 약간 뒤떨어집니다.

memcache는 다중 프로세스이며 비차단입니다. 캐시로만 사용되는 경우 memcache가 더 적합합니다.

Redis는 어떻게 재고 동시성 문제를 해결하고 수량 제어를 달성합니까?

1. 예를 들어 키 키가 이미 Redis에 존재하는지 확인하는 명령이 있습니다. ,exes mycounter

set set mycounter 99

get과 같은 키 값을 설정하고 초기화합니다. getmycounter

incr과 같은 키 값을 가져옵니다. 1씩 증가합니다. 예를 들어 incrmycounter //출력 결과는 100

incrby 증분을 지정합니다. incrbymycounter 2 와 같은 값 //출력 결과는 102

지정 incrbymycounter -2 와 같은 값을 줄입니다. //출력 결과는 100

setnx 값이 없으면 값이 성공적으로 설정됩니다. setnxmycounter 99 //출력 결과는 0입니다. 이는 설정이 실패했음을 의미하며 redis

setnx key1 12 // 출력 결과는 1이며, 이는 이전에 Redis에 존재하지 않았음을 의미합니다.

expire 만료 mycounter 30과 같이 키의 수명 주기를 설정합니다. //유효 기간을 30초로 설정합니다.

ttl ttlmycounter와 같은 키 만료 시간을 가져옵니다. //출력은 13입니다. 이는 아직 13초가 남았음을 의미합니다. .반환이 -1이면 메모리가 부족하지 않는 한 만료되지 않으며 항상 Redis 캐시에 존재한다는 의미입니다.

//반환이 -2이면 Redis가 만료되었음을 의미합니다. 키 값을 사용하여 확인할 수 있습니다. 0을 반환하면 재고가 없음을 의미합니다

2. 일반적인 상황

상품 구매 폭주로 인해 수량 조절이 불가능하여 재고가 한도를 초과하여 부족 현상이 발생합니다. 소송 비용. (예: 인벤토리가 1,000개인데 사용자가 2,000개의 아이템을 성공적으로 구매했는데 인벤토리가 부족합니다.)

복권은 한정되어 있어 관리하지 않으면 돈이 너무 많이 쓰게 됩니다

빨간 봉투를 집으세요

3. 흐름도 및 코드

옵션 1 흐름도:

옵션 2의 흐름도:Redis는 어떻게 재고 동시성 문제를 해결하고 수량 제어를 달성합니까?

//方案1代码,测试坏境TP5
public function redisCountV1(){
    Log::record("测试版本1并发开始", Log::INFO);
    $redis = new Redis();
    //总库存数量
    $amountLimit = 100;
    //redis存储库存键名
    $keyName = "mycounter_v6";
    //假设每次消耗库存数为1
    $incrAmount = 1;
    //判断redis中是否 存在该值,如果不存在,则用set设置(问题是如果出现并发,两个或多个用户同时访问,会导致库存重新设置)
    if(!$redis->exists($keyName)){
        $redis->set($keyName, 95);
    }
    //从redis中取出当前库存数
    $currAmount = $redis->get($keyName);
    //如果当前库存数+增长的库存数>总库存,直接返回
    if($currAmount + $incrAmount > $amountLimit) {
        file_put_contents("/Users/han/Documents/www/cs/testv1.log", "bad luck \n", FILE_APPEND);
        Log::record("bad luck", Log::INFO);
        return false;
    }
    //缓存库存数量增加
    $redis->incrby($keyName, $incrAmount);
    file_put_contents("/Users/han/Documents/www/cs/testv1.log", "good luck \n", FILE_APPEND);
    Log::record("good luck", Log::INFO);
}

//测试方式:ab  -c 100 -n 200 http://www.fenleduo.com:8080/V7/Test/redisCountV1
//方案2代码,测试坏境TP5
public function redisCountV2(){
    Log::record("测试版本2并发开始", Log::INFO);
    $redis = new Redis();
    //总库存数量
    $amountLimit = 100;
    //redis存储库存键名
    $keyName = "mycounter_v12";
    //假设每次消耗库存数为1
    $incrAmount = 1;
    //判断redis中是否 存在该值,如果不存在,则用setnx设置(注:如果出现并发,两个或多个用户同时访问,不会导致库存重新设置)
    if(!$redis->exists($keyName)){
        //setnx 如果不存在该值,则设置,如果存在则不会设置
        $redis->setnx($keyName, 95);
    }
    //从redis中取出当前库存数
    $currAmount = $redis->get($keyName);
    //如果当前库存数+增长的库存数>总库存,直接返回
    if($redis->incrby($keyName, $incrAmount) > $amountLimit) {
        file_put_contents("/Users/han/Documents/www/cs/testv2.log", "bad luck \n",FILE_APPEND);
        Log::record("bad luck", Log::INFO);
        return false;
    }
    file_put_contents("/Users/han/Documents/www/cs/testv2.log", "good luck \n",FILE_APPEND);
    Log::record("good luck", Log::INFO);
}
//测试方式:ab  -c 100 -n 200 http://www.fenleduo.com:8080/V7/Test/redisCountV2

위 내용은 Redis는 어떻게 재고 동시성 문제를 해결하고 수량 제어를 달성합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제