cas
(요구사항: Workerman 버전 >= 3.3.0)
bool \GlobalData\Client::cas(string $key, mixed $old_value, mixed $new_value)
원자적 교체로, $new_value로 $old_value를 교체합니다.
오직 현재 클라이언트가 마지막으로 값을 가져온 후, 해당 key에 대한 값이 다른 클라이언트에 의해 수정되지 않은 경우에만 값을 쓸 수 있습니다.
매개변수
$key
키 값입니다. (예: $global->abc에서 abc는 키 값입니다.)
$old_value
이전 데이터입니다.
$new_value
새 데이터입니다.
반환값
교체에 성공하면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
설명:
다중 프로세스가 동시에 동일한 공유 변수를 조작할 때, 종종 동시성 문제를 고려해야 합니다.
예를 들어 A와 B 두 개의 프로세스가 동시에 사용자 목록에 구성원을 추가합니다.
A와 B 프로세스는 현재 사용자 목록이 $global->user_list = array(1,2,3)입니다.
A 프로세스는 $global->user_list 변수를 조작하여 사용자 4를 추가합니다.
B 프로세스는 $global->user_list 변수를 조작하여 사용자 5를 추가합니다.
A 프로세스가 변수 $global->user_list = array(1,2,3,4)를 설정하는 데 성공합니다.
B 프로세스가 변수 $global->user_list = array(1,2,3,5)를 설정하는 데 성공합니다.
이때 B 프로세스가 설정한 변수가 A 프로세스가 설정한 변수를 덮어써서 데이터 손실이 발생합니다.
위의 예는 읽기와 설정이 원자적 작업이 아니기 때문에 동시성 문제를 야기합니다.
이런 동시성 문제를 해결하기 위해 cas 원자적 교체 인터페이스를 사용할 수 있습니다.
cas 인터페이스는 값을 변경하기 전에,
$old_value에 따라 이 값이 다른 프로세스에 의해 변경되었는지 판단합니다.
변경된 경우에는 교체하지 않고 false를 반환하며, 그렇지 않으면 true를 반환합니다.
다음 예제를 참조하십시오.
주의:
일부 공유 데이터가 동시적으로 덮어씌워지는 것은 문제가 되지 않을 수 있습니다. 예를 들어 경매 시스템의 현재 최대 입찰가나 특정 상품의 현재 재고 수량 등이 있습니다.
예제
$global = new GlobalData\Client('127.0.0.1:2207');
// 목록 초기화
$global->user_list = array(1,2,3);
// user_list에 원자적으로 값을 추가합니다.
do
{
$old_value = $new_value = $global->user_list;
$new_value[] = 4;
}
while(!$global->cas('user_list', $old_value, $new_value));
var_export($global->user_list);