배경
최근 회사의 많은 팀이 php7을 업그레이드했습니다. 현재 php7 읽기 mc를 지원하는 유일한 확장은 memcached입니다. 하지만 회사 내 많은 프로젝트에서는 사용자 세션 데이터를 저장하고 불러오기 위해 mc 클러스터를 공유하게 되는데, 저장할 때 로그인 시 배열 형태로 쓰기 위해 memcache 확장을 사용합니다. 읽을 때는 memcache를 사용하는 것이 당연합니다. 확장을 사용하여 배열 형태로 읽어냅니다. 하지만 이제는 memcached를 통해서만 읽을 수 있습니다. 그런데 제가 아는 한, 배열 형태로 데이터를 읽을 때 둘이 서로 호환되지 않는데, 그 이유를 알고 싶습니다.
확인
memcache 확장과 memcached 확장 읽기 및 쓰기 배열 데이터가 호환되지 않는지 확인합니다. 테스트 스크립트:
<?php echo "========== test string ============\n"; $mc = new memcache; $mc->addServer('10.199.189.129', 11511); $key = 'testString'; $mc->set($key, 'test success'); var_dump($mc->get($key)); $mc2 = new memcached; $mc2->addServer('10.199.189.129', 11511); var_dump($mc2->get($key)); echo "========== test array ============\n"; $key2 = 'testArray'; $mc->set($key2, [1,2,3]); var_dump($mc->get($key2)); var_dump($mc2->get($key2));
실행 결과:
➜ ~ php /apps/dat/test.php ========== test string ============ string(12) "test success" string(12) "test success" ========== test array ============ array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } int(0)
결과로 볼 때 당사의 이전 진술이 확인되었습니다.
이유를 맞춰보세요
문자열에는 문제가 없으므로 배열 형식에 문제가 있습니다. 그래서 배열이 mc에 저장될 때의 직렬화 방법이 다르다고 의심됩니다. 그래서 추가 테스트를 진행했습니다. 테스트 스크립트 작성
<?php echo "========== test array ============\n"; $mc = new memcache; $mc->addServer('10.199.189.129', 11511); $mc2 = new memcached; $mc2->addServer('10.199.189.129', 11511); $key2 = 'testArray1'; $key3 = 'testArray2'; $mc->set($key2, [1,2,3]); $mc2->set($key3, [1,2,3]); var_dump($mc->get($key2)); var_dump($mc2->get($key3));
실행 결과:
➜ ~ php /apps/dat/test.php ========== test array ============ array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
그런 다음 mc에 직접 연결하여
➜ ~ telnet 10.199.189.129 11511 Trying 10.199.189.129... Connected to 10.199.189.129 Escape character is '^]'. get testArray1 VALUE testArray1 1 30 a:3:{i:0;i:1;i:1;i:2;i:2;i:3;} END get testArray2 VALUE testArray2 4 30 a:3:{i:0;i:1;i:1;i:2;i:2;i:3;} END
결과를 확인합니다. 보세요, memcache와 memcached가 mc에 쓴 결과가 동일하다는 것을 알 수 있습니다. 이는 우리의 추측이 틀렸다는 것을 의미합니다. 두 값의 직렬화 처리는 완전히 동일하며 차이점은 값의 다른 플래그에 있습니다. Memcache가 배열 데이터를 저장할 때 falg는 1이고 memcached는 4입니다. 우리는 mc 값의 플래그가 사용자가 사용자 정의할 수 있도록 제공되어 읽을 때 다양한 처리를 용이하게 한다는 것을 알고 있습니다. 그런데 왜 두 플래그 정의가 다른가요? 이 질문을 염두에 두고 두 확장의 소스 코드를 읽어보고 이유를 찾아보세요.
두 확장 프로그램의 소스 코드 읽기
memcache
php_memcache.h:
#define MMC_SERIALIZED 1 #define MMC_COMPRESSED 2
memcached
php_memcached.c
#define MEMC_VAL_IS_STRING 0 #define MEMC_VAL_IS_LONG 1 #define MEMC_VAL_IS_DOUBLE 2 #define MEMC_VAL_IS_BOOL 3 #define MEMC_VAL_IS_SERIALIZED 4 #define MEMC_VAL_IS_IGBINARY 5 #define MEMC_VAL_IS_JSON 6 #define MEMC_VAL_IS_MSGPACK 7
소스 코드를 읽어보니 memcache는 배열 형식의 플래그를 1로 정의하고, memcached는 값에 대한 세부 유형 구분을 위해 데이터 유형을 string, long으로 정의하는 것을 발견했습니다. php로 mc에 저장됩니다. double 등과 같은 데이터 유형입니다. 즉, memcache를 사용할 때
<?php $mc = new memcache; $mc->addServer('10.199.189.129', 11511); $mc->set('123',1); var_dump($mc->get('123'));
을 실행한 결과는 다음과 같습니다.
string(1) "1"
분명히 값 1로 키를 저장했지만, When it is a 끈. 그리고 memcached를 사용할 때
<?php$mc = new memcached; $mc->addServer('10.199.189.129', 11511); $mc->set('123',1); var_dump($mc->get('123'));
을 실행하면 실행 결과는
int(1)
결론
입니다.memcache 확장과 memcached 확장이 배열 데이터 읽기 및 쓰기에 호환되지 않는 이유는 memcached가 데이터 유형을 세부적으로 구분하기 위해 다양한 데이터 유형의 식별자를 정의하고, 배열의 식별자가 배열 식별자와 일치하지 않기 때문입니다. memcache로 정의됩니다.
memcache 확장과 memcached 확장이 직접 작성한 데이터가 서로 읽을 수 있도록 하기 위해 mc는 문자열 형식으로만 작성할 수 있습니다.
이번 조사를 통해 Memcached가 Memcache보다 나은 점이 많다는 사실도 깨달았습니다. PHP7의 인기로 인해 Memcache는 빠른 속도로 역사 속에서 사라질 것이라고 믿습니다.