데이터 경쟁은 공유 데이터에 동시에 액세스하는 여러 프로세스 또는 스레드를 나타냅니다. 적어도 하나의 프로세스 또는 스레드는 데이터를 작성하여 프로그램의 불안정한 실행 결과 또는 예측할 수없는 동작을 초래합니다. PHP에서, 특히 APC 캐시를 사용할 때, 캐시 된 데이터가 일반적으로 공유되기 때문에, 여러 요청이 동일한 캐시 키에 동시에 기록되면 데이터 레이스 문제가 발생할 수 있습니다.
APCU_ENTRY 기능의 기능은 캐시에 이미 지정된 키 값 쌍이 있는지 확인하는 것입니다. 그렇지 않은 경우 콜백 함수를 실행하여 데이터를 생성하고 캐시에 저장합니다. 정상적인 상황에서는 캐시 고장의 중복 계산 문제를 효과적으로 피할 수 있지만 동시 시나리오에서는 동일한 캐시 키에서 여러 요청이 동시에 작동하면 다음 문제가 발생할 수 있습니다.
반복 계산 : 캐시가 발생하지 않지만 여러 요청이 동시에 발생하면 여러 요청이 동시에 콜백 함수에 들어가 동시에 동일한 결과를 반복하여 계산하여 리소스 낭비가 발생할 수 있습니다.
불일치 : 캐시 작업이 콜백 함수에서 수행되므로 동시 작업으로 인해 데이터 덮어 쓰기 또는 불일치가 발생할 수 있습니다.
데이터 경쟁 문제를 해결하기 위해 APCU_ENTRY 의 사용은 다음과 같은 방식으로 최적화 될 수 있습니다.
가장 일반적인 방법은 잠금 메커니즘을 사용하여 하나의 프로세스 만 캐시 쓰기를 한 번에 수행 할 수 있도록하는 것입니다. PHP에서는 파일 잠금, Redis, Memcached 등을 사용하여 잠금을 구현할 수 있습니다. 다음은 파일 잠금을 사용하는 간단한 구현입니다.
$cache_key = 'my_cache_key';
$lock_key = $cache_key . '_lock';
if (apcu_exists($lock_key)) {
// 잠금이 이미 존재하는 경우,잠시 기다렸다가 다시 시도하십시오
sleep(1);
} else {
// 잠금 장치를 추가하십시오
apcu_store($lock_key, true, 10); // 잠금 만료 시간은입니다10두번째
// 캐시 된 값을 생성합니다
$value = generate_cache_value();
// 캐시 된 값을 저장하십시오
apcu_store($cache_key, $value);
// 잠금을 해제하십시오
apcu_delete($lock_key);
}
잠금 장치를 사용하면 동시에 하나의 프로세스 만 캐시 생성 콜백 로직으로 입력하여 반복 계산을 피할 수 있습니다.
APCU_ADD 함수는 APCU_ENTRY 함수와 유사하지만 기존 캐시 값을 덮어 쓰는 것을 피합니다. 따라서 캐시 키가 존재하는지 확인하기 만하면 APCU_ADD를 사용하여 데이터 경쟁 가능성을 줄일 수 있습니다.
$value = apcu_add('my_cache_key', generate_cache_value(), 3600);
캐시 키가 이미 존재하는 경우 APCU_ADD는 이를 덮어 쓰지 않아서 동시성 중에 생성 된 인종 조건이 줄어 듭니다.
또 다른 간단한 방법은 콜백 함수를 입력하기 전에 캐시가 이미 존재하는지 확인하는 것입니다. 여러 요청이 동시에 실행될 때 반복 계산을 피하십시오. 별도의 플래그는 캐시가 계산 중인지 계산되었는지 여부를 기록하는 데 사용될 수 있습니다. 예를 들어:
$cache_key = 'my_cache_key';
if ($result = apcu_fetch($cache_key)) {
// 캐시 히트,직접 사용하십시오
} else {
// 캐시 미스,계산 상태를 확인하십시오
$status_key = $cache_key . '_status';
if (!apcu_exists($status_key)) {
// 계산되지 않은 징후가 없습니다,계산으로 표시하십시오
apcu_store($status_key, true);
// 캐시 된 가치 생성 작업을 수행하십시오
$result = generate_cache_value();
// 스토리지 캐시
apcu_store($cache_key, $result);
// 계산 상태 플래그를 제거하십시오
apcu_delete($status_key);
} else {
// 다른 요청이 캐시 작동을 완료 할 때까지 기다립니다
while (!$result = apcu_fetch($cache_key)) {
sleep(1);
}
}
}
이러한 방식으로, 여러 요청이 동일한 캐시 키에서 동시에 작동하면 첫 번째 요청 만 캐시가 생성되며 나머지 요청은 캐시 생성이 완료 될 때까지 기다립니다.
캐시 된 데이터가 매우 중요하고 일관성에 대한 요구 사항이 높으면 동시 환경에서 데이터 일관성을 보장하기 위해 데이터베이스 트랜잭션과 유사한 메커니즘을 사용하는 것을 고려할 수 있습니다. APC는 트랜잭션을 직접 지원하지 않지만 데이터베이스 트랜잭션 또는 외부 캐싱 시스템 (예 : REDIS)을 사용하여 유사한 효과를 달성 할 수 있습니다.