Use MySQL trigger to synchronize data

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/

Guess you like

Origin www.cnblogs.com/chinatrump/p/11416199.html