? ? 想到用perl操作memcache的原因,是因为需要从一个数据库里取数据,然后插入另外一个数据库中(从mysql里取数据,插入到postgresql),mysql是在用的数据库,而postgresql则是存放所有历史数据的。由于不是实时取的,在一段时间间隔里,可能会有大量的数据需要取,如果是直接取一条插一条的话,可能时间会比较慢,并且影响到数据库的性能。
? ? 所以就想如果能把取出来的数据尽可能快的存放到一个地方去,然后再从那个地方取出来存放到postgresql,这样即不影响Mysql的性能,也提高的效率。常用的存储介质中自然是放到内存里最快的了,然后就想到nosql,在这么多的nosql产品中,memcache比较熟悉,故此,就选用了memcache,将要取的数据先存放到memcache里,然后,再从memcache里取数据存放到postgresql里。
? ? 思路有了,然后就开始实施了,要操作memcache、mysql、postgresql,需要安装相应的perl模块,cpan直接搞定,下面的代码是测试的代码:
- ?
- use?strict;?
- use?Data::Dumper;?
- use?DBI;?
- use?DBD::Pg;?
- use?Cache::Memcached;?
- ?
- my?$dbname='zabbix';?
- my?$uname='zabbix';?
- my?$pw='zabbix';?
- my?$host='192.168.65.219';?
- my?$port="5432";?
- my?$mc_expires=500000;?
- ?
- ?
- my?$dbh=DBI->connect("dbi:Pg:dbname=$dbname;host=$host;port=$port",$uname,$pw,{AutoCommit?=>?1});?
- ?
- ?
- my?$sth=$dbh->prepare("select?*?from?history?where?clock?<?1348037308;");?
- $sth->execute();?
- ?
- ?
- my?$mem?=?new?Cache::Memcached({?
- ?????servers?=>["192.168.65.219:11211"],?
- ?????});?
- $mem->set_connect_timeout(0.1);?
- ?
- my?$row;?
- ?
- my?%row_hash;?
- while($row?=?$sth?->?fetchrow_hashref)?
- {?
- ?
- ??my?$zb_itemid=$row?->?{itemid};?
- ?my?$zb_value=$row?->?{value};?
- ??my?$zb_ns=$row?->?{ns};?
- ?
- ??my?$key=$row->{clock};?
- ??printf("$keyn");?
- ?
- ?
- ??$mem->set($key,{$key=>{zb_itemid=>"$zb_itemid",zb_value=>"$zb_value",zb_ns=>"$zb_ns"}});?
- ??my?$test?=?$mem->get($key);?
- ??printf("$test->{$key}->{zb_itemid}n");?
- ??print?Dumper($test)?.?"n";?
? ?上面代码操作zabbix的数据库的,目的是从现在正在使用的zabbix数据库中,取出history这张表的数据出来,存放到memcache里去,然后再从memcache里取数据,存放到postgresql数据库里去。
? ?这里取出的数据以clock为key,其他字段为value,存放到memcache里去,perl操作memcache和php操作有些不一致,php可以将多个字段的值存放在一个数组里,然后再将这个数组作为value存放到memcache里。
? 但perl不行,如果直接将数组作为value的话,则只能将数组的第一个值存放到memcache里,那么数组的引用可以吗?这样是可以的,如下代码:
- while($row?=?$sth?->?fetchrow_hashref)?
- {?
- ?
- ??my?$zb_itemid=$row?->?{itemid};?
- ??my?$zb_value=$row?->?{value};?
- ??my?$zb_ns=$row?->?{ns};?
- ?
- ??my?@data=("$zb_itemid","$zb_value","$zb_ns");?
- ??my?$insert_data=@data;?
- ??
- ?$mem->set($key,$insert_data,$mc_expires);?
- ??my?$test=$mem->get($key);?
- ??print?Dumper($test)?.?"n";?
? 得到如下的数据结构:

? 从得到的数据结构来看,$mem->get($key)得到的是数组的引用,要得到真实的数据,还得解引用,如下方式:
- printf("$test->[0]??$test->[1]??$test->[2]n");?
? 这样才能得到真实的数据。如果这样操作的话,只能按照数组的下标来操作数据。
? 在cpan里的例子是这样来操作memcache的:
- $memd->set("my_key",?"Some?value");?
- $memd->set("object_key",?{?'complex'?=>?[?"object",?2,?4?]});?
?这样是以一个匿名hash的方式来存放一组数据的,具体的操作方式还可以有以下几种:
- ?
- $mem->set($key,{array1122?=>?['a11','b22','c333']});?
- ?
- $mem->set($key,{someone?=>?{aaa?=>?"bbb",?444?=>?"dddd"});?
- ?
- $mem->set($key,{sss?=>?"eee"});?
? 以上操作可以单独用,也可以混合用,可以根据实际情况来定。
? 写完这篇博客的时候,最终要用到哪种方式,还没确定好。