mirror of
https://github.com/php-win-ext/php-memcached.git
synced 2026-03-24 00:52:18 +01:00
Added Memcached Session Replicas by changes below
1. Allow for automatic removal of failed server to session handler (MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS) 2. Allow X number of replicas (MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS) 3. Added option for consistent hasing (MEMCACHED_BEHAVIOR_KETAMA) 4. Added error msg when session handler couldn't obtain a lock
This commit is contained in:
@@ -17,7 +17,24 @@ memcached.sess_lock_wait = 150000
|
||||
; the default value is "memc.sess.key."
|
||||
memcached.sess_prefix = "memc.sess.key."
|
||||
|
||||
|
||||
; Allow consistent hasing for the session
|
||||
memcached.sess_consistent_hashing = 1
|
||||
|
||||
; Allow failed memcached server to automatically be removed
|
||||
memcached.sess_remove_failed = 1
|
||||
|
||||
; Write data to a number of additional memcached servers
|
||||
; This is "poor man's HA" as libmemcached calls it.
|
||||
; If this value is positive and sess_remove_failed is enabled
|
||||
; when a memcached server fails the session will continue to be available
|
||||
; from a replica. However, if the failed memcache server
|
||||
; becomes available again it will read the session from there
|
||||
; which could have old data or no data at all
|
||||
memcached.sess_num_replicas = 0;
|
||||
|
||||
; memcached session binary mode
|
||||
; libmemcached replicas only work if binary mode is enabled
|
||||
memcached.sess_binary = Off
|
||||
|
||||
; Set the compression type
|
||||
|
||||
@@ -288,6 +288,9 @@ PHP_INI_BEGIN()
|
||||
STD_PHP_INI_ENTRY("memcached.sess_binary", "0", PHP_INI_ALL, OnUpdateBool, sess_binary_enabled, zend_php_memcached_globals, php_memcached_globals)
|
||||
STD_PHP_INI_ENTRY("memcached.sess_lock_wait", "150000", PHP_INI_ALL, OnUpdateLongGEZero,sess_lock_wait, zend_php_memcached_globals, php_memcached_globals)
|
||||
STD_PHP_INI_ENTRY("memcached.sess_prefix", "memc.sess.key.", PHP_INI_ALL, OnUpdateString, sess_prefix, zend_php_memcached_globals, php_memcached_globals)
|
||||
STD_PHP_INI_ENTRY("memcached.sess_consistent_hashing", "0", PHP_INI_ALL, OnUpdateBool, sess_consistent_hashing_enabled, zend_php_memcached_globals, php_memcached_globals)
|
||||
STD_PHP_INI_ENTRY("memcached.sess_num_replicas", "0", PHP_INI_ALL, OnUpdateLong, sess_num_replicas, zend_php_memcached_globals, php_memcached_globals)
|
||||
STD_PHP_INI_ENTRY("memcached.sess_remove_failed", "0", PHP_INI_ALL, OnUpdateBool, sess_remove_failed_enabled, zend_php_memcached_globals, php_memcached_globals)
|
||||
#endif
|
||||
STD_PHP_INI_ENTRY("memcached.compression_type", "fastlz", PHP_INI_ALL, OnUpdateCompressionType, compression_type, zend_php_memcached_globals, php_memcached_globals)
|
||||
STD_PHP_INI_ENTRY("memcached.compression_factor", "1.3", PHP_INI_ALL, OnUpdateReal, compression_factor, zend_php_memcached_globals, php_memcached_globals)
|
||||
@@ -3034,6 +3037,9 @@ static void php_memc_init_globals(zend_php_memcached_globals *php_memcached_glob
|
||||
#ifdef HAVE_MEMCACHED_SESSION
|
||||
MEMC_G(sess_locking_enabled) = 1;
|
||||
MEMC_G(sess_binary_enabled) = 1;
|
||||
MEMC_G(sess_consistent_hashing_enabled) = 0;
|
||||
MEMC_G(sess_num_replicas) = 0;
|
||||
MEMC_G(sess_remove_failed_enabled) = 0;
|
||||
MEMC_G(sess_prefix) = NULL;
|
||||
MEMC_G(sess_lock_wait) = 0;
|
||||
MEMC_G(sess_locked) = 0;
|
||||
|
||||
@@ -66,6 +66,9 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached)
|
||||
zend_bool sess_locked;
|
||||
char* sess_lock_key;
|
||||
int sess_lock_key_len;
|
||||
long sess_num_replicas;
|
||||
zend_bool sess_remove_failed_enabled;
|
||||
zend_bool sess_consistent_hashing_enabled;
|
||||
#endif
|
||||
char *serializer_name;
|
||||
enum memcached_serializer serializer;
|
||||
|
||||
@@ -48,6 +48,7 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
|
||||
char *lock_key = NULL;
|
||||
int lock_key_len = 0;
|
||||
unsigned long attempts;
|
||||
long write_retry_attempts = 0;
|
||||
long lock_maxwait;
|
||||
long lock_wait = MEMC_G(sess_lock_wait);
|
||||
time_t expiration;
|
||||
@@ -64,6 +65,11 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
|
||||
expiration = time(NULL) + lock_maxwait + 1;
|
||||
attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait);
|
||||
|
||||
/* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */
|
||||
if (MEMC_G(sess_remove_failed_enabled)) {
|
||||
write_retry_attempts = MEMC_G(sess_num_replicas) * ( memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1);
|
||||
}
|
||||
|
||||
lock_key_len = spprintf(&lock_key, 0, "lock.%s", key);
|
||||
do {
|
||||
status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0);
|
||||
@@ -73,6 +79,11 @@ static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
|
||||
MEMC_G(sess_lock_key_len) = lock_key_len;
|
||||
return 0;
|
||||
} else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) {
|
||||
if (write_retry_attempts > 0) {
|
||||
write_retry_attempts--;
|
||||
continue;
|
||||
}
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Write of lock failed");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -195,6 +206,30 @@ success:
|
||||
}
|
||||
}
|
||||
|
||||
if (MEMC_G(sess_consistent_hashing_enabled)) {
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_KETAMA, (uint64_t) 1) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached consistent hashing");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow libmemcached remove failed servers */
|
||||
if (MEMC_G(sess_remove_failed_enabled)) {
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, (uint64_t) 1) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set: remove failed servers");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow replicas section */
|
||||
long num_replicas = MEMC_G(sess_num_replicas);
|
||||
if (num_replicas > 0) {
|
||||
/* Set the number of replicas libmemcached will use */
|
||||
if (memcached_behavior_set(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, (uint64_t) num_replicas) == MEMCACHED_FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to set memcached client replicating");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -243,6 +278,7 @@ PS_READ_FUNC(memcached)
|
||||
|
||||
if (MEMC_G(sess_locking_enabled)) {
|
||||
if (php_memc_sess_lock(memc_sess->memc_sess, key TSRMLS_CC) < 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to clear session lock record");
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -263,6 +299,7 @@ PS_WRITE_FUNC(memcached)
|
||||
{
|
||||
int key_len = strlen(key);
|
||||
time_t expiration = 0;
|
||||
long write_try_attempts = 1;
|
||||
memcached_return status;
|
||||
memcached_sess *memc_sess = PS_GET_MOD_DATA();
|
||||
size_t key_length;
|
||||
@@ -277,13 +314,22 @@ PS_WRITE_FUNC(memcached)
|
||||
if (PS(gc_maxlifetime) > 0) {
|
||||
expiration = PS(gc_maxlifetime);
|
||||
}
|
||||
status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0);
|
||||
|
||||
if (status == MEMCACHED_SUCCESS) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
/* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server plus the initial write */
|
||||
if (MEMC_G(sess_remove_failed_enabled)) {
|
||||
write_try_attempts = 1 + MEMC_G(sess_num_replicas) * ( memcached_behavior_get(memc_sess->memc_sess, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1);
|
||||
}
|
||||
|
||||
do {
|
||||
status = memcached_set(memc_sess->memc_sess, key, key_len, val, vallen, expiration, 0);
|
||||
if (status == MEMCACHED_SUCCESS) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
write_try_attempts--;
|
||||
}
|
||||
} while (write_try_attempts > 0);
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
PS_DESTROY_FUNC(memcached)
|
||||
|
||||
Reference in New Issue
Block a user