您好,欢迎访问一九零五行业门户网

memcache与mysql数据库同步

1:mysql memcached udf 其实就是通过libmemcached来使用memcache的一系列函数,通过这些函数,你能对memcache进行get, set, cas, append, prepend, delete, increment, decrement objects操作,如果我们通过mysql trigger来使用这些函数,那么就能通过mysql
1:mysql memcached udf 其实就是通过libmemcached来使用memcache的一系列函数,通过这些函数,你能 对memcache进行get, set, cas, append, prepend, delete, increment, decrement objects操作,如果我们通过mysql trigger来使用这些函数,那么就能通过mysql更好的,更自动的管理memcache!
2:安装方法:
1)安装memcache
2)安装libmemcached
shell> cd libmemcached-0.35
shell> ./configure --with-memcached=/usr/local/bin/memcached
shell> make && make install
shell> echo /usr/local/lib >> /etc/ld.so.conf
shell> ldconfig
3)安装memcached_functions_mysql
shell> tar zxvf memcached_functions_mysql-0.9.tar.gz
shell> cd memcached_functions_mysql-0.9
shell> ./configure --with-mysql=/usr/local/mysql51/bin/mysql_config --with-libmemcached =/usr/local/
shell> make && make install
4)拷贝lib文件到mysql的plugin下面
shell> cp -r /usr/local/lib/libmemcached_functions_mysql.* /usr/local/mysql51/lib/mysql/plugin/
5)添加memcache udf 函数
在mysql里执行 source install_functions.sql
这样我们就可以使用mysql memcached udf 了,我们可以通过下面语句查看是否已经正常安装
1)查看mysql.func,有很多函数
mysql> select * from mysql.func;
+------------------------------+-----+---------------------------------+----------+
| name                         | ret | dl                              | type     |
+------------------------------+-----+---------------------------------+----------+
| memc_add                     |   2 | libmemcached_functions_mysql.so | function |
| memc_add_by_key              |   2 | libmemcached_functions_mysql.so | function |
| memc_servers_set             |   2 | libmemcached_functions_mysql.so | function |
2)添加trigger,看是否向memcache里insert、update等
具体的语句,我们可以参照:
1)memcached_functions_mysql-0.9/sql 目录下的trigger_fun.sql
2)使用参照文档:http://dev.mysql.com/doc/refman/5.1/en/ha-memcached-interfaces-mysqludf.html
我们还必须注意以下几点:
1)mysql 编译时一定不要带'--with-mysqld-ldflags=-all-static' 这个参数,因为这样就限制了mysql 的动态安装功能了
2)使用时,要观察mysql.err日志,不知道是有意还是无意,udf更新memcache都会记录在err日志里,注意清理该日志,否则一下就爆满了
3)mysql 官网有这样一句话:
the list of servers used by the memcached udfs is not persistent over restarts of the mysql server. if the mysql server fails, then you must re-set the list of memcached servers.
所以,当我们重启mysql,我们必须通过select  memc_servers_set('192.168.0.1:11211,192.168.0.2:11211');语句重新注册memcache服务器!
2、创建mysql的insert,update,delete触发器更新memcache,参考http://blog.csdn.net/jiedushi/article/details/6176940
测试环境在linux下进行,版本系统为centos5.
以下为相关软件,包括其版本和下载地址:
mysql-5.1.30 下载
memcached-1.2.6 下载
libevent-1.4.7-stable 下载
memcached_functions_mysql-1.1 下载
libmemcached-0.26 下载
编译安装mysql,安装因个人细好而定,省略许多与测试无关的编译细节及参数。
[c] view plaincopyprint?
[root@localhost ~]#tar xzf mysql-5.1.30.tar_001.gz  [root@localhost ~]#cd mysql-5.1.30  [root@localhost ~]#./configure --prefix=/usr/local/mysql51  [root@localhost ~]#make  [root@localhost ~]#make install  [root@localhost ~]#./scripts/mysql_install_db --user=mysql --skip-name-resolve  [root@localhost ~]#/usr/local/mysql51/bin/mysqld_safe  省略列出安装memcached和libevent的相关命令,具体可按照实际情况安装,测试时我将libevent默认安装,memcached安装于/usr/local/memcached目录下。
启动memcached.
[c] view plaincopyprint?
/usr/local/memcached/bin/memcached -d -m 50 -u root -p 11211  编译安装libmemcache.
[c] view plaincopyprint?
[root@localhost ~]#tar xzf libmemcached-0.26.tar.gz  [root@localhost ~]#cd libmemcached-0.26  [root@localhost ~]#./configure --with-memcached=/usr/local/memcached/bin/memcached  [root@localhost ~]# make && make install  编译安装memcache udfs for mysql.
[c] view plaincopyprint?
[root@localhost ~]# tar xzf memcached_functions_mysql-1.1.tar.gz  [root@localhost ~]# cd memcached_functions_mysql-1.1  [root@localhost ~]# ./configure --with-mysql-config=/usr/local/mysql51/bin/mysql_config  [root@localhost ~]# make && make install  编译完成后将编译好的库文件复制到mysql的插件目录下,以便于加载使用。
[c] view plaincopyprint?
cp /usr/local/lib/libmemcached_functions_mysql* /usr/local/mysql51/lib/mysql/plugin/  进入memcached_functions_mysql的源码目录,在目录下有相关添加udf的sql文件用于初始化。
在mysql的shell中执行memcached_functions_mysql源码目录下的sql/install_functions.sql
或者运行memcached_functions_mysql源码目录下utils/install.pl这个perl脚本,把memcache function作为udf加入mysql。
[root@localhost ~]# mysql
检查安装是否成功
mysql> select name,dl from mysql.func;
二. 测试用例设计情况:
(1).新建两张表:urls和results,用来更新urls表里面的内容,让系统自动更新memcached的内容。results用来记录更新memcached失败的记录。
sql语句如下:
use tests;
drop table if exists urls;
create table `urls` (
  `id` int(10) not null,
  `url` varchar(255) not null default '',
  primary key (`id`)
);
drop table if exists results;
create table `results` (
  `id` int(10) not null,
  `result` varchar(255) not null default 'error',
  `time` timestamp null default current_timestamp,
  primary key (`id`)
);
(2). 建立三个trigger.
当向urls表里面插入数据时,对memcached执行set操作,trigger如下:
delimiter //
drop trigger if exists url_mem_insert;
create trigger url_mem_insert
before insert on urls
for each row begin
    set @mm = memc_set(new.id, new.url);
    if @mm 0 then
    insert into results(id) values(new.id);
    end if;
end //
delimiter ;
当对urls表里面的数据进行更新时,对memcached执行replace操作,trigger如下:
delimiter //
drop trigger if exists url_mem_update;
create trigger url_mem_update
before update on urls
for each row begin
    set @mm = memc_replace(old.id,new.url);
    if @mm 0 then
    insert into results(id) values(old.id);
    end if;
end //
delimiter ;
当对urls表里面的数据进行删除操作时,对memcached执行delete操作,trigger如下:
delimiter //
drop trigger if exists url_mem_delete;
create trigger url_mem_delete
before delete on urls
for each row begin
    set @mm = memc_delete(old.id);
    if @mm 0 then
    insert into results(id) values(old.id);
    end if;
end //
delimiter ;
(3). 设置memcached相关参数
设置同时udf操作的memcaced的机器ip和端口:
mysql> select memc_servers_set('192.168.3.184:11900');
+---------------------------------------+
| memc_servers_set('192.168.3.184:11900') |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
1 row in set (0.00 sec)
mysql> select memc_server_count();
+---------------------+
| memc_server_count() |
+---------------------+
|                   1 |
+---------------------+
1 row in set (0.00 sec)
在mysql命令行列出可以修改memcached参数的行为:
mysql> select memc_list_behaviors()/g
*************************** 1. row ***************************
memc_list_behaviors():
memcached server behaviors
memcached_behavior_support_cas
memcached_behavior_no_block
memcached_behavior_tcp_nodelay
memcached_behavior_hash
memcached_behavior_cache_lookups
memcached_behavior_socket_send_size
memcached_behavior_socket_recv_size
memcached_behavior_buffer_requests
memcached_behavior_ketama
memcached_behavior_poll_timeout
memcached_behavior_retry_timeout
memcached_behavior_distribution
memcached_behavior_buffer_requests
memcached_behavior_user_data
memcached_behavior_sort_hosts
memcached_behavior_verify_key
memcached_behavior_connect_timeout
memcached_behavior_ketama_weighted
memcached_behavior_ketama_hash
memcached_behavior_binary_protocol
memcached_behavior_snd_timeout
memcached_behavior_rcv_timeout
memcached_behavior_server_failure_limit
memcached_behavior_io_msg_watermark
memcached_behavior_io_bytes_watermark
1 row in set (0.00 sec)
设置memcached_behavior_no_block为打开状态,这样在memcached出现问题时(不能连接时)
数据继续插入到mysql中,报错提示,如果不设置此值,如果memcached失败,mysql需要等到timeout
才可以插入到表中。
mysql> select memc_servers_behavior_set('memcached_behavior_no_block','1');
+--------------------------------------------------------------+
| memc_servers_behavior_set('memcached_behavior_no_block','1') |
+--------------------------------------------------------------+
|                                                            0 |
+--------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select memc_servers_behavior_set('memcached_behavior_tcp_nodelay','1');
+-----------------------------------------------------------------+
| memc_servers_behavior_set('memcached_behavior_tcp_nodelay','1') |
+-----------------------------------------------------------------+
|                                                               0 |
+-----------------------------------------------------------------+
1 row in set (0.00 sec)
三. 简单的功能测试:
1. 向表urls里面插入数据,然后查memcached是否也set进数据:
mysql> insert into urls (id,url) values (1, 'http://www.sina.com.cn');
query ok, 1 row affected, 1 warning (0.00 sec)
mysql> select memc_get('1');  
+------------------------+
| memc_get('1')          |
+------------------------+
| http://www.sina.com.cn |
+------------------------+
1 row in set (0.00 sec)
1> telnet 192.168.3.184 11900
trying 192.168.3.184...
connected to 192.168.3.184 (192.168.3.184).
escape character is '^]'.
get 1
value 1 0 22
http://www.sina.com.cn
end
2.更新表urls里面的数据,然后查询memcached里面是否也更新:
mysql> update test.urls set url='http://blog.sina.com.cn' where id=1;
query ok, 1 row affected, 1 warning (0.00 sec)
rows matched: 1  changed: 1  warnings: 0
mysql> select memc_replace('1','http://blog.sina.com.cn'); 
+---------------------------------------------+
| memc_replace('1','http://blog.sina.com.cn') |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
1 row in set (0.00 sec)
mysql> select memc_get('1');  
+-------------------------+
| memc_get('1')           |
+-------------------------+
| http://blog.sina.com.cn |
+-------------------------+
1 row in set (0.00 sec)
1> telnet 192.168.3.184 11900
trying 192.168.3.184...
connected to 192.168.3.184 (192.168.3.184).
escape character is '^]'.
get 1
value 1 0 23
http://blog.sina.com.cn
end
3.删除表urls里面的数据,然后查memcached是否也删除:
mysql> delete from test.urls where id=1;
query ok, 1 row affected, 1 warning (0.00 sec)
rows matched: 1  changed: 1  warnings: 0
mysql> select memc_get('1');  
+---------------+
| memc_get('1') |
+---------------+
| null          |
+---------------+
1 row in set (0.00 sec)
1> telnet 192.168.3.184 11900
trying 192.168.3.184...
connected to 192.168.3.184 (192.168.3.184).
escape character is '^]'.
get 1
end
四. 利用php脚本insert, update,delete表urls里面的数据,进行测试。
每条记录的平均长度是:17k
单独向表urls里面插入10万条记录需要的时间为:75秒
单独对表urls里面更新10万条记录需要的时间为:70秒
单独对表urls里面删除10万条记录需要的时间为:105秒
同时进行30万数据的insert,update, delete操作需要时间为:241秒
上面操作都没有memcached失败情况:
mysql> select * from results;
empty set (0.00 sec)
测试脚本如下:
插入脚本:
0> more a.php
更新脚本:
0> more b.php
删除脚本:
0> more c.php
五. 结论:
测试依赖的环境比较多,可能数据会不准确。整体来看速度还不错。
适合项目应用相对比较小的场合。
优点:
触发器中使用 udfs 直接更新 memcached 的内容,减轻了应用程序设计和编写的复杂性。
缺点:
1. 如果出现mysql服务重启,需要重新设置连接memcached关系(select memc_servers_set('192.168.3.184:11900'))
2. 有可能存在bug问题,导致mysql的crash(测试时没遇到:)).
真正的线上环境比这个复杂很多。我想到的需要考虑的问题:
1. 网络因素,mysql和memcached是否放在同一idc,他们之间的网络性能是否很好。网络性能越好,速度肯定越快,如果使用本机的memcached能适当的减少网络开销。
2. 插入的数据量,向mysql插入每条记录的size,以及向memcached里面更新的数据size大小。更新mysql,memcached的数据size越大,更新的速度越慢。
所以前期规划好,在memcached里面存那两列(key-value)是关键。
3. 延时问题需要考虑,mysql所在机器如果资源使用比较狠,会导致更新memcached慢(出现类似m/s的延时问题)。
4. 考虑容灾问题,如果两者中有down出现时,需要考虑怎么恢复,当前的测试是这样考虑的:建一张错误表,如果在出现更新mc出现问题时,自动把更新错误的记录插到
一张表里面,通过查这张表,可以知道哪些数据在什么时间更新错误,如果应用于生产环境,需要考虑监控和出现问题时恢复工作(写好脚本完善这个工作)。
5. mysql自身因素,例如执行的mysql语句效率,以及连接mysql的client程序(php)的连接开销等等。
参考
http://blog.sina.com.cn/s/blog_499740cb0100g45p.html
http://www.libing.name/2009/02/06/mysql-map-data-to-memcached.html
其它类似信息

推荐信息