Before attempting to do Memcache data between remote synchronization, use Gearman with message handling process as data is written to the message queue, including network discovery and performance testing through the line performance gap between different places is very obvious, even in the case of off-site increase the number of message handling process is still difficult to synchronize data traffic increases. Judging from the delay may be due to different places between green or much higher than the network, Memcache low-latency read and write IO operations such requests seriously affected by network latency (if Memcache support batch write may be able to alleviate this a problem). So think of the solution is to avoid the use of high latency networks do Memcache read and write operations, will soon pass the data to be synchronized to the other end, then you can avoid making written to the impact of network latency brings.
For the data synchronization to the other end, can be performed by a number of database replication mechanism, generally easier to think of the Redis, the case of time-List write data, the other end of the loop to read data using a script using the synchronization method BLPOP. This is also a good way, the difficulty lies in the need to synchronize data on their own development process, the process needs to have better performance and stability, as well as the need for maintenance and monitoring.
However, when it comes to data replication mechanism, my first thought is MySQL, the data by using the Blackhole Engine binlog way synchronized to the other end, the reliability is higher than Redis-- copy interrupt recoverable, there binlog data recording is good. For the synchronization process is performed in two ways, one is reading the copy process by over binlog, the difficulty of this approach is that still need to develop their own synchronization process, difficult to synchronize using Redis similar Another method is to use a trigger synchronization, each receiving an INSERT statement to execute an operation corresponding to Memcache, there is also need to use MySQL libmemcached UDF.
1. Install the MySQL libmemcached UDF
The UDF MySQL installation is very simple, first download [libmemcached UDF source] (https://launchpad.net/memcached-udfs https://launchpad.net/memcached-udfs), which relies libmemcached, too, and you can not use the new version, 0.31 Centos6 use is possible. Proceed as follows ./configure make make install cp /usr/local/lib/libmemcached_functions_mysql.so /usr/lib64/mysql/plugin/ mysql -u root < sql/install_functions.sql
2. Start multiple MySQL instances
In order to facilitate the testing and final deployment you may need to use more than the MySQL instance, where the record about methods of operation, first initialize the two MySQL data directory
mysql_install_db --user=mysql --datadir=/var/lib/mysql/3306/ mysql_install_db --user=mysql --datadir=/var/lib/mysql/3307/
Then use a configuration similar to the following documents, since only need to use the Blackhole Engine, most of the parameters are not much sense, set a relatively small but save some resources
[mysqld_multi] mysqld = /usr/bin/mysqld_safe mysqladmin = /usr/bin/mysqladmin [mysqld3306] port = 3306 socket = /var/lib/mysql/3306/mysqld.sock datadir = /var/lib/mysql/3306 key_buffer_size = 16M max_allowed_packet = 1M table_open_cache = 64 sort_buffer_size = 512K net_buffer_length = 8K read_buffer_size = 256K read_rnd_buffer_size = 512K myisam_sort_buffer_size = 8M log-bin=mysql-bin binlog_format=mixed server-id = 3306 innodb_data_file_path = ibdata1:10M:autoextend innodb_buffer_pool_size = 16M innodb_additional_mem_pool_size = 2M innodb_log_file_size = 5M innodb_log_buffer_size = 8M innodb_flush_log_at_trx_commit = 2 innodb_lock_wait_timeout = 50 [mysqld3307] port = 3307 socket = /var/lib/mysql/3307/mysqld.sock datadir = /var/lib/mysql/3307 key_buffer_size = 16M max_allowed_packet = 1M table_open_cache = 64 sort_buffer_size = 512K net_buffer_length = 8K read_buffer_size = 256K read_rnd_buffer_size = 512K myisam_sort_buffer_size = 8M log-bin=mysql-bin binlog_format=mixed server-id = 3307 innodb_data_file_path = ibdata1:10M:autoextend innodb_buffer_pool_size = 16M innodb_additional_mem_pool_size = 2M innodb_log_file_size = 5M innodb_log_buffer_size = 8M innodb_flush_log_at_trx_commit = 2 innodb_lock_wait_timeout = 50
Examples of the multi-start as follows, starting two instances
mysqld_multi start 3306 mysqld_multi start 3307
3. Initialize libmemcached UDF
Manually initialize libmemcached UDF after starting MySQL, Memcache provided corresponding server, and set a distributed hashing method, the initialization script is as follows
SELECT memc_servers_set('127.0.0.1:11211,127.0.0.1:11212'); SELECT memc_servers_behavior_set('MEMCACHED_BEHAVIOR_DISTRIBUTION', 'MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA'); SELECT memc_servers_behavior_set('MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED', 1);
Note that the above need to be initialized every time you start MySQL, the following test to see if the initialization is successful, return a written explanation success
SELECT memc_set('abc', '123'); +------------------------+ | memc_set('abc', '123') | +------------------------+ | 1 | +------------------------+ SELECT memc_get('abc'); +-----------------+ | memc_get('abc') | +-----------------+ | 123 | +-----------------+
4. libmemcached UDF modify support custom flags
libmemcached UDF has a big disadvantage is that Memcache flags parameter-coded 0, and we need the original flags values are also synchronized during the synchronized, so the need for the code of conduct libmemcached UDF little adjustment here only changed the set method, other modifications of the method are similar.
diff -Nur memcached_functions_mysql-1.1/src/args.c memcached_functions_mysql-1.1.patched/src/args.c --- memcached_functions_mysql-1.1/src/args.c 2009-11-11 10:56:52.000000000 +0800 +++ memcached_functions_mysql-1.1.patched/src/args.c 2015-09-19 10:11:59.062512226 +0800 @@ -120,6 +120,30 @@ case MEMC_ADD_BY_KEY: case MEMC_REPLACE: case MEMC_REPLACE_BY_KEY: + { + + if (args->arg_count >= max_args - 1) + { + if (args->arg_type[max_args - 2] == STRING_RESULT) + { + container->flags= (uint32_t)atoi(args->args[max_args - 2]); + } + else if (args->arg_type[max_args - 2] == INT_RESULT) + { + container->flags= *((uint32_t*)args->args[max_args -2]); + } + else + { + container->flags= (uint32_t)0; + } + + } + else + { + container->flags= (uint32_t) 0; + } + fprintf(stderr, "flags %dn", (int) container->expiration); + } case MEMC_APPEND: case MEMC_APPEND_BY_KEY: case MEMC_PREPEND: diff -Nur memcached_functions_mysql-1.1/src/common.h memcached_functions_mysql-1.1.patched/src/common.h --- memcached_functions_mysql-1.1/src/common.h 2009-11-15 06:53:23.000000000 +0800 +++ memcached_functions_mysql-1.1.patched/src/common.h 2015-09-19 09:50:30.480512194 +0800 @@ -11,6 +11,7 @@ struct memc_function_st { unsigned int offset; time_t expiration; + uint32_t flags; memcached_st memc; memcached_result_st results; memcached_string_st *stats_string; diff -Nur memcached_functions_mysql-1.1/src/set.c memcached_functions_mysql-1.1.patched/src/set.c --- memcached_functions_mysql-1.1/src/set.c 2009-11-11 10:56:52.000000000 +0800 +++ memcached_functions_mysql-1.1.patched/src/set.c 2015-09-19 10:01:36.611512903 +0800 @@ -30,7 +30,7 @@ unsigned int count; memc_function_st *container; - container= prepare_args(args, message, MEMC_SET, 2, 3); + container= prepare_args(args, message, MEMC_SET, 2, 4); if (container == NULL) return 1; @@ -67,7 +67,7 @@ rc= memcached_set(&container->memc, args->args[0], (size_t)args->lengths[0], args->args[1], (size_t)args->lengths[1], - container->expiration, (uint16_t)0); + container->expiration, container->flags); return (rc != MEMCACHED_SUCCESS) ? (long long) 0 : (long long) 1; }
So adjusted memc_set method in the third parameter is the flags, the fourth parameter is the expiration time, do not pass by default to zero.
5. PHP Memcached module, a method of increasing the write raw data acquired
Since PHP Memcached module will save the data as a sequence of data, compression processing, and in synchronization UDF difficult to do the same approach, so you need to deal with PHP Memcached module after obtaining it, we PHP Memcached getPayload a method of increasing the module to achieve this function, which is implemented as follows
static zend_function_entry memcached_class_methods[] = { //... MEMC_ME(getPayload, arginfo_getPayload) { NULL, NULL, NULL } }; ZEND_BEGIN_ARG_INFO_EX(arginfo_getPayload, 0, 0, 1) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(1, flags) ZEND_END_ARG_INFO() static PHP_METHOD(Memcached, getPayload) { zval* zflags = NULL; uint32_t flags; zval* value; char *payload; size_t payload_len; MEMC_METHOD_INIT_VARS; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &value, &zflags) == FAILURE) { return; } MEMC_METHOD_FETCH_OBJECT; if (i_obj->compression) { flags |= MEMC_VAL_COMPRESSED; } if (i_obj->serializer == SERIALIZER_IGBINARY) { flags |= MEMC_VAL_IGBINARY; } payload = php_memc_zval_to_payload(value, &payload_len, &flags TSRMLS_CC); if (zflags != NULL) { convert_to_long(zflags); ZVAL_LONG(zflags, flags); } RETURN_STRINGL(payload, payload_len, 0); }
Using the following effects
<?php $mem = new Memcached(); var_dump($mem->getPayload(array(), $flags), $flags);
Enter the following
string(6) "a:0:{}" int(1)
5. establishing synchronization trigger data table box
Table for establishing synchronization, which is structured as follows in Table
CREATE TABLE `MemcQueue` ( `k` varchar(250) NOT NULL, `expiration` int(11) NOT NULL, `flags` int(10) unsigned NOT NULL, `v` mediumblob NOT NULL, PRIMARY KEY (`k`) ) ENGINE=BLACKHOLE DEFAULT CHARSET=latin1
In the establishment of the flip-flop from the library
DELIMITER | CREATE TRIGGER queue_trigger AFTER INSERT ON MemcQueue FOR EACH ROW BEGIN SET @mm = memc_set(new.k, new.v, new.flags, new.expiration); END |
6. Test results
Original link large column https://www.dazhuanlan.com/2019/08/15/5d55107d28e42/