Designing and developing a distributed server-side program that can control the client is a blessing and can be done with a lot of things to the client, and it can be done elegantly. The role determines the fate, in the Internet architecture, the Web server must be charged before, destined to the multi-browser version and protocol compatibility with painstaking efforts. But if the Web server is backend, it will be much better, can let the service-side program to isolate, distributed features are supported and implemented by the client. Memcache is the design pattern. Memcache is the back-end architecture must be a weapon, about its principle and source code analysis can be directly Google, no longer say in this. In recent projects to consider the problem of redundancy and fault tolerance, the memcache redundancy mechanism analysis, only for your reference.
Why
Consistent hash ensures that when a machine is added to or removed from an existing machine group, it does not cause a wide range of changes in the hash mapping relationship. But a cache machine down, the content is not, the cache needs to be rebuilt, the database pressure will rise, if the cache machine down too much, there will be a cache avalanche, failure is inevitable. If a key=value can be stored on multiple machines, one down and the other on the top, it is not very good, this is the redundancy mechanism. Unfortunately, Memcached does not support this feature.
It‘s not! Surprise! Memcached is a caching layer for your application. It is not designed to have any data redundancy.
Obviously memcached itself does not want to do this feature, once again to throw the task to the client. There is a need to achieve, pecl/memcache after 3.0 has begun to support this mechanism.
If data integrity is of greater importance a real replicating memcached backend such as "repcached" is recommended.
This feature can be turned on by configuring Memcache:
memcache.redundancy = # default 1
How
The following is a Pecl/memcache 3.0.6 code analysis of redundancy specific implementation.
First look at the relevant code for the set operation:
/* schedule the first request */
mmc = mmc_pool_find(pool, key, key_len TSRMLS_CC);
result = mmc_pool_schedule(pool, mmc, request TSRMLS_CC);
/* clone and schedule redundancy-1 additional requests */
for (i=0; i < redundancy-1 && i < pool->num_servers-1; i++) {
mmc_queue_push(&skip_servers, mmc);
mmc = mmc_pool_find_next(pool, key, key_len, &skip_servers, &last_index TSRMLS_CC);
if (mmc_server_valid(mmc TSRMLS_CC)) {
mmc_pool_schedule(pool, mmc, mmc_pool_clone_request(pool, request TSRMLS_CC) TSRMLS_CC);
}
}
It can be seen that after set a key=value, the set Redundancy-1 a clone. The transformation of the specific key in the Mmc_pool_find_next function:
/* find the next server not present in the skip-list */
do {
keytmp_len = sprintf(keytmp, "%s-%d", key, (*last_index)++);
mmc = pool->hash->find_server(pool->hash_state, keytmp, keytmp_len TSRMLS_CC);
} while (mmc_queue_contains(skip_servers, mmc) && *last_index < MEMCACHE_G(max_failover_attempts));
The key transformation rules are simple, 1 to N (key-i), N-Times set.
Get is, of course, to be looked up in the same way. However, if a valid server is found, it stops looking and returns.
mmc_t *mmc = pool->hash->find_server(pool->hash_state, key, key_len TSRMLS_CC);
/* check validity and try to failover otherwise */
if (!mmc_server_valid(mmc TSRMLS_CC) && MEMCACHE_G(allow_failover)) {
unsigned int last_index = 0;
do {
mmc = mmc_pool_find_next(pool, key, key_len, NULL, &last_index TSRMLS_CC);
} while (!mmc_server_valid(mmc TSRMLS_CC) && last_index < MEMCACHE_G(max_failover_attempts));
}
Think
Memcache is achieved by transforming a key=value into n key=value to achieve redundancy, This can and 3.0.0 before the interface is very good compatibility, but redundancy key needs to transform and randomly scattered on the machine, each time to hash find, also very bad management. I think of a kind of redundancy design, is to introduce the concept of group, when adding the machine, the configuration belongs to the group ID, a key only hash to a group ID, all the requests are sent to group,group inside each machine storage hash ( Key) to the full contents of the group. This set/get only needs a single hash operation, and can also design a more flexible implementation within the group.
This is just a little personal idea, welcome everyone to make bricks.
Analysis and thinking on the mechanism of Memcache redundancy