2017-10-10 14 views
1

우리는 서빙 머신에서 64 노드 Redis 클러스터에 연결하기 위해 phpredis 라이브러리를 사용합니다. 우리가 지속적인 연결을 사용하더라도 php가 요청을 통해 객체를 재사용하지 않기 때문에 모든 요청은 CLUSTER SLOTS 먼저 Redis Cluster를 호출 한 다음 데이터를 가져옵니다. API와 Redis 모두에서 CPU가 증가하고 캐시 될 수있는 메타 정보 (CLUSTER SLOTS)에 대한 네트워크 사용량이 증가하므로 비용이 많이 드는 것으로 나타났습니다. 기본적으로 우리는 같은 php-fpm 프로세스에서 여러 요청에 걸쳐 Redis 클러스터 연결 객체를 다시 사용하기를 원합니다. 이 작업을 수행하는 방법에 대한 제안 사항은 무엇입니까?phpredis Redis 클러스터 연결 객체를 다시 사용합니다.

업데이트 : cluster_library.c 코드에서 다음 diff를 시도했지만 PHP에서 임의의 런타임 예외가 발생하는 것 같습니다. 여기 phpredis의

index 3e532b7..b2cbf16 100644 
--- a/cluster_library.c 
+++ b/cluster_library.c 
@@ -7,6 +7,10 @@ 
#include <zend_exceptions.h> 

extern zend_class_entry *redis_cluster_exception_ce; 
+int cache_count = 0; 
+//Cache the cluster slots value for every n requests/calls, n being 100 for now 
+int CACHE_COUNT_VAL = 10; 
+clusterReply *permSlots=NULL; 

/* Debugging methods/ 
static void cluster_dump_nodes(redisCluster *c) { 
@@ -939,7 +943,18 @@ PHP_REDIS_API int cluster_map_keyspace(redisCluster *c TSRMLS_DC) { 
     } 

     // Parse out cluster nodes. Flag mapped if we are valid 
-  slots = cluster_get_slots(seed TSRMLS_CC); 
+ if (permSlots && cache_count <= CACHE_COUNT_VAL) { 
+   slots = permSlots; 
+   cache_count++; 
+ } 
+ else { 
+   slots = cluster_get_slots(seed TSRMLS_CC); 
+ } 
+ 
     if (slots) { 
      mapped = !cluster_map_slots(c, slots); 
      // Bin anything mapped, if we failed somewhere 
@@ -951,8 +966,16 @@ PHP_REDIS_API int cluster_map_keyspace(redisCluster *c TSRMLS_DC) { 
     if (mapped) break; 
    } ZEND_HASH_FOREACH_END(); 

+ if((!permSlots && mapped && slots) || 
+    cache_count >= CACHE_COUNT_VAL) { 
+ permSlots = slots; 
+ cache_count = 0; 
+ } 
+ 
    // Clean up slots reply if we got one 
- if(slots) cluster_free_reply(slots, 1); 
+ // if(slots) cluster_free_reply(slots, 1); 

    // Throw an exception if we couldn't map 
    if(!mapped) { 

답변

2

개발자. 현재 이것은 새로운 요청마다 CLUSTER SLOTS 명령을 내야하기 때문에 phpredis의 한계/결함입니다. 지금까지 내가 이것을 피할 수있는 유일한 방법은 phpredis를 Codis 또는 Corvis과 같은 프록시로 지정하는 것입니다. 그러나이 프록시를 사용하는 개인적인 경험은 없습니다.

즉, 나는 this 브랜치에이 기능에 대한 실험적 지원을 구현했습니다. PHP의 persistent_list을 사용하여 여러 요청에서 슬롯 정보를 캐시합니다.

Redis Cluster 채택이 증가하고있는 것처럼 보입니다. 저는 이것을 메인 라인 개발 지사로 곧 출시 할 예정이며, 아마도 다음 안정적인 릴리스로 전환하려고 노력할 것입니다!

건배, 마이크

마이크는, 그러나, 나는 cluster_get_slots (씨앗 TSRMLS_CC)를 호출하지 않도록 cluster_map_keyspace 명령을 변경하여 단순한 솔루션을 시도
+0

감사합니다; 매번 전역 변수에 슬롯을 캐시합니다. 나는 또한 cluster_free_reply (slots, 1)가 슬롯 메모리를 비우지 말 것을 요청했다. 독립 실행 형 시나리오에서 작동하지만 php-fpm + nginx 설정에서 실패합니다. 왜 이런 일이 일어나고 있는지에 대한 생각? – sreeraag

+0

젠드 프레임 워크는 자체 할당자를 제공하기 때문에, 변수를 비우는 것을 잊은 후에 정리할 것입니다. 따라서 요청간에 컨텍스트를 유지하려면 persistent_list 또는 이와 유사한 것을 사용해야합니다. 영구 메모리 (pemalloc)를 할당하려고 시도 할 수는 있지만 권장하지 않습니다. :) –

+0

이것에 대해 전혀 몰랐습니다! 감사합니다 마이크! 하지만 이것은 독립 PHP 프로세스가있는 테스트 스크립트에서 작동하지만 이상한 nginx + phpfpm 설정에서 실패했습니다. 왜 pemalloc을 추천하지 않습니까? 또한 클러스터 슬롯 응답을 파일에 직렬화하고 매번 파일에서 가져 오는 것에 대해 생각하고있었습니다. 이것이 좋은 생각이라고 생각합니까? 또는 persistent_list를 사용하는 지점에서는 CLUSTER SLOTS를 캐싱하지 않는다고 생각합니다. 어떻게 활성화합니까? – sreeraag