16.2.3.4 通过Perl使用 MySQL 和memcached

该模块为 Memcache 协议提供了一个本地接口,并为memcachedCache::Memcached提供的核心功能提供支持。使用操作系统的包管理系统或使用以下命令安装模块: CPAN

#> perl -MCPAN -e 'install Cache::Memcached'

要通过模块从 Perl 使用memcachedCache::Memcached,首先要创建一个新 Cache::Memcached对象来定义服务器列表和连接的其他参数。唯一的参数是包含缓存接口选项的散列。例如,要创建一个使用三个 memcached服务器的新实例:

use Cache::Memcached;

my $cache = new Cache::Memcached {
    'servers' => [
        '198.51.100.100:11211',
        '198.51.100.101:11211',
        '198.51.100.102:11211',
	],
};
笔记

Cache::Memcached接口与多个服务器一起使用时,API 会自动在组中的所有服务器上执行某些操作。例如,通过 获取统计信息 Cache::Memcached返回一个散列,其中包含逐个主机的数据,以及组中所有服务器的一般统计信息。

通过将选项指定为选项散列的一部分,您可以在创建缓存对象实例时设置其他属性。或者,您可以在实例上使用相应的方法:

  • servers或方法 set_servers():指定要使用的服务器列表。服务器列表应该是对服务器数组的引用,每个元素都是地址和端口号的组合(用冒号分隔)。您还可以通过 Unix 套接字指定本地连接(例如/tmp/sock/memcached)。要指定具有权重的服务器(指示服务器在散列过程中应使用的频率),请指定一个包含 memcached服务器实例和权重数的数组引用。数字越大优先级越高。

  • compress_threshold或 method set_compress_threshold():指定压缩值时的阈值。大于指定数量的值 zlib在存储和检索期间会自动压缩(使用 )。

  • no_rehash或方法 set_norehash():如果原始选择不可用,则禁用查找新服务器。

  • readonly或方法 :禁用对内存缓存服务器 set_readonly()的写入 。

配置Cache::Memcached对象实例后,您可以使用set()get()方法从memcached服务器存储和检索信息。Storable存储在缓存中的对象使用该模块 自动序列化和反序列化。

Cache::Memcached接口支持以下用于存储/检索数据的方法,并与表中所示的通用方法相关。

Cache::Memcached功能 等效的通用方法
get() 通用get()的。
get_multi(keys) keys仅使用一个查询从内存缓存中获取多个。返回键值对的哈希引用。
set() 通用set()的。
add() 通用add()的。
replace() 通用replace()的。
delete() 通用delete()的。
incr() 通用incr()的。
decr() 通用decr()的。

下面是将 memcached与 Perl 和 Cache::Memcached模块一起使用的完整示例:

#!/usr/bin/perl

use Cache::Memcached;
use DBI;
use Data::Dumper;

# Configure the memcached server

my $cache = new Cache::Memcached {
    'servers' => [
                   'localhost:11211',
                   ],
    };

# Get the film name from the command line
# memcached keys must not contain spaces, so create
# a key name by replacing spaces with underscores

my $filmname = shift or die "Must specify the film name\n";
my $filmkey = $filmname;
$filmkey =~ s/ /_/;

# Load the data from the cache

my $filmdata = $cache->get($filmkey);

# If the data wasn't in the cache, then we load it from the database

if (!defined($filmdata))
{
    $filmdata = load_filmdata($filmname);

    if (defined($filmdata))
    {

# Set the data into the cache, using the key

	if ($cache->set($filmkey,$filmdata))
        {
            print STDERR "Film data loaded from database and cached\n";
        }
        else
        {
            print STDERR "Couldn't store to cache\n";
	}
    }
    else
    {
     	die "Couldn't find $filmname\n";
    }
}
else
{
    print STDERR "Film data loaded from Memcached\n";
}

sub load_filmdata
{
    my ($filmname) = @_;

    my $dsn = "DBI:mysql:database=sakila;host=localhost;port=3306";

    $dbh = DBI->connect($dsn, 'sakila','password');

    my ($filmbase) = $dbh->selectrow_hashref(sprintf('select * from film where title = %s',
                                                     $dbh->quote($filmname)));

    if (!defined($filmname))
    {
     	return (undef);
    }

    $filmbase->{stars} =
	$dbh->selectall_arrayref(sprintf('select concat(first_name," ",last_name) ' .
                                         'from film_actor left join (actor) ' .
                                         'on (film_actor.actor_id = actor.actor_id) ' .
                                         ' where film_id=%s',
                                         $dbh->quote($filmbase->{film_id})));

    return($filmbase);
}

该示例使用 Sakila 数据库,从数据库中获取电影数据并将电影和演员的复合记录写入memcached。当为不存在的电影调用它时,您会得到以下结果:

$> memcached-sakila.pl "ROCK INSTINCT"
Film data loaded from database and cached

访问已添加到缓存中的电影时:

$> memcached-sakila.pl "ROCK INSTINCT"
Film data loaded from Memcached