memcached在Zorpia的应用
http://www.zorpia.com 是一个网页相册,博客,交友,论坛的大型网站公司。现在已有超过140万活跃使用者遍布美国,香港,东南亚,欧洲,澳洲,亚洲等其它地区。每天的访问量都在增长,已成为全世界排名第五的社会生活关系网。
Memcached也采用了memcached来提高网站的访问速度,并且取得了很好的效果,我在负责zorpia的memcached项目时候积累了一些经验,主要的做法如下:
1) 通过对memcache的perl客户端进行包装,定制自己的客户端。
2) 通过制定符合zorpia规范的hash key命名规范
? ? memcache中需要存储的内容的key均由string组成。
这个string统一由一个memcache.pm的subroutine来实现。(假设这个subroutine是 get_key() )
? ? memcache中存放两种形式的数据
(1) result of SQL query :
(2) 普通变量(variable)
这两种数据的key的组合方式是不相同的,由get_key进行判断和完成
? ? 关于get_key 和 naming rule
get_key subroutine完成所有memcache key的命名,naming rule也是在它里边体现:
(1)输入参数 -- hash结构,里边定义了当前需要存放的数据的信息
结构
(2)返回值 -- string,返回数据的key_name
?必须确定 get_key 的传入hash的结构,
hash中主要有两个元素
type --- 定义当前数据结构的类型 ,有 'var' , 'sql'两种值
object --- 存放当前数据结构的详细信息,
当 type eq 'var'时,object表示变量的名字,该名字由程序员指定
当 type eq 'sql'时,object包含所存放sql的主要基本信息,hash结构,也由程序员按照规则制定
## 当variable 数据类型,比较简单
$var_hash = {
type => 'var', ## var表示当前类型是 variable
object => 'language', ## language代表variable的名字
};
生成的key是Zorpia::var| language
## sql 数据
比如select first_name from user where user_id =2那么hash为
$sql_hash = {
type => 'sql',
object => {
table => {table2=>"user",}, ## sql 查询的表
column => {column1=>"first_name",}, ## sql所要查询的column
condition => { user_id =>"2",}, ## sql条件
},
};
生成的key是Zorpia::sql|user|first_name| user_id =2
get_key subroutine必须对传入hash进行判断,对不同类型的数据按照不同的方式组合,形成key,返回给使用者。这个key,必须保证其唯一性:
比如:所有字母小写,一些数组在组合成key之前必须首先排序
? ? get_key函数
sub get_key{
my $hash = shift;
return undef unless $hash && ref $hash eq "HASH";
my $type = $hash->{type};
my $key_name;
if ($type eq 'sql') {
my ($table_key,$column_key,$condition_key);
$table_key=_get_key($hash->{object}->{table});
$column_key=_get_key($hash->{object}->{column});
$condition_key=_get_key($hash->{object}->{condition});
$key_name = join('|',$type,$table_key,$column_key,$condition_key);
#Currently the length limit of a key is set at 250 characters
if (length($key_name)>250)
{
$key_name=substr(0,250,$key_name);
}
}
elsif($type eq 'var')
{
$key_name = join('|',$type,$hash->{object});
}
return $key_name;
}
sub _get_key
{
my $hash=shift;
return undef unless $hash && ref $hash eq "HASH";
my ($t,$ret,$i);
foreach $i (sort keys %$hash)
{
$i=~s/^/s+|/s+$//g;
$hash->{$i}=~s/^/s+|/s+$//g;
push(@$t,lc("$i=$hash->{$i}"));
}
$ret=join(':',sort { $a cmp $b } @$t);
return $ret;
}
3) 制定需要应用memcached的规则
?经常访问的表user,user_details
?合理设定变量在memcached的生存周期
?将活跃用户的信息预先导入到memcached
?分别在多台机器上启动多个memcached服务
?编写脚本监控memcached服务是否活动
4) User表的具体应用举例
? 在 select时候
先查询memcahce里有没有,有的话,返回;否则从数据库select,在memcache里设置,返回。
my $sql_hash = {
type => 'sql',
object => {
table => {table1=>"user",},
column => {column1=>"user_id",},
condition => {email=>$user_id,},
},
};
my $key=Zorpia::MemCache::get_key($sql_hash);
my $user_id_by_email=Zorpia::MemCache::get($key);
if(!$user_id_by_email)
{
my $sth;
my $query ="select user_id from user where email=?";
$sth = $dbh->prepare($query);
$sth->execute($user_id);
my $user1 = $sth->fetchrow_hashref();
$user_id_by_email=$user1->{'user_id'};
Zorpia::MemCache::set($key,$user_id_by_email,1800);
}
?在 update,insert,delete时候
先在数据库update,insert,delete,在memcache里设置,返回。
&Zorpia::DB::data_entry_no_return($dbh,"user","COUNT(*)","$account_information_insert_statement user_id=$current_user_id", "user_id=$current_user_id");
#add by kelly
my $sql_hash = {
type => 'sql',
object => {
table => {table1=>"user",},
column => {column1=>"user_id",},
condition => {user_id=>$current_user_id,},
},
};
my $key=Zorpia::MemCache::get_key($sql_hash);
my $query = "SELECT *, user_id AS id FROM user WHERE user_id=?";
my $sth_memc = $dbh->prepare($query);
$sth_memc->execute($current_user_id);
my $user_memc = $sth_memc->fetchrow_hashref();
&Zorpia::MemCache::set($key,$user_memc,21600);
http://www.zorpia.com 是一个网页相册,博客,交友,论坛的大型网站公司。现在已有超过140万活跃使用者遍布美国,香港,东南亚,欧洲,澳洲,亚洲等其它地区。每天的访问量都在增长,已成为全世界排名第五的社会生活关系网。
Memcached也采用了memcached来提高网站的访问速度,并且取得了很好的效果,我在负责zorpia的memcached项目时候积累了一些经验,主要的做法如下:
1) 通过对memcache的perl客户端进行包装,定制自己的客户端。
2) 通过制定符合zorpia规范的hash key命名规范
? ? memcache中需要存储的内容的key均由string组成。
这个string统一由一个memcache.pm的subroutine来实现。(假设这个subroutine是 get_key() )
? ? memcache中存放两种形式的数据
(1) result of SQL query :
(2) 普通变量(variable)
这两种数据的key的组合方式是不相同的,由get_key进行判断和完成
? ? 关于get_key 和 naming rule
get_key subroutine完成所有memcache key的命名,naming rule也是在它里边体现:
(1)输入参数 -- hash结构,里边定义了当前需要存放的数据的信息
结构
(2)返回值 -- string,返回数据的key_name
?必须确定 get_key 的传入hash的结构,
hash中主要有两个元素
type --- 定义当前数据结构的类型 ,有 'var' , 'sql'两种值
object --- 存放当前数据结构的详细信息,
当 type eq 'var'时,object表示变量的名字,该名字由程序员指定
当 type eq 'sql'时,object包含所存放sql的主要基本信息,hash结构,也由程序员按照规则制定
## 当variable 数据类型,比较简单
$var_hash = {
type => 'var', ## var表示当前类型是 variable
object => 'language', ## language代表variable的名字
};
生成的key是Zorpia::var| language
## sql 数据
比如select first_name from user where user_id =2那么hash为
$sql_hash = {
type => 'sql',
object => {
table => {table2=>"user",}, ## sql 查询的表
column => {column1=>"first_name",}, ## sql所要查询的column
condition => { user_id =>"2",}, ## sql条件
},
};
生成的key是Zorpia::sql|user|first_name| user_id =2
get_key subroutine必须对传入hash进行判断,对不同类型的数据按照不同的方式组合,形成key,返回给使用者。这个key,必须保证其唯一性:
比如:所有字母小写,一些数组在组合成key之前必须首先排序
? ? get_key函数
sub get_key{
my $hash = shift;
return undef unless $hash && ref $hash eq "HASH";
my $type = $hash->{type};
my $key_name;
if ($type eq 'sql') {
my ($table_key,$column_key,$condition_key);
$table_key=_get_key($hash->{object}->{table});
$column_key=_get_key($hash->{object}->{column});
$condition_key=_get_key($hash->{object}->{condition});
$key_name = join('|',$type,$table_key,$column_key,$condition_key);
#Currently the length limit of a key is set at 250 characters
if (length($key_name)>250)
{
$key_name=substr(0,250,$key_name);
}
}
elsif($type eq 'var')
{
$key_name = join('|',$type,$hash->{object});
}
return $key_name;
}
sub _get_key
{
my $hash=shift;
return undef unless $hash && ref $hash eq "HASH";
my ($t,$ret,$i);
foreach $i (sort keys %$hash)
{
$i=~s/^/s+|/s+$//g;
$hash->{$i}=~s/^/s+|/s+$//g;
push(@$t,lc("$i=$hash->{$i}"));
}
$ret=join(':',sort { $a cmp $b } @$t);
return $ret;
}
3) 制定需要应用memcached的规则
?经常访问的表user,user_details
?合理设定变量在memcached的生存周期
?将活跃用户的信息预先导入到memcached
?分别在多台机器上启动多个memcached服务
?编写脚本监控memcached服务是否活动
4) User表的具体应用举例
? 在 select时候
先查询memcahce里有没有,有的话,返回;否则从数据库select,在memcache里设置,返回。
my $sql_hash = {
type => 'sql',
object => {
table => {table1=>"user",},
column => {column1=>"user_id",},
condition => {email=>$user_id,},
},
};
my $key=Zorpia::MemCache::get_key($sql_hash);
my $user_id_by_email=Zorpia::MemCache::get($key);
if(!$user_id_by_email)
{
my $sth;
my $query ="select user_id from user where email=?";
$sth = $dbh->prepare($query);
$sth->execute($user_id);
my $user1 = $sth->fetchrow_hashref();
$user_id_by_email=$user1->{'user_id'};
Zorpia::MemCache::set($key,$user_id_by_email,1800);
}
?在 update,insert,delete时候
先在数据库update,insert,delete,在memcache里设置,返回。
&Zorpia::DB::data_entry_no_return($dbh,"user","COUNT(*)","$account_information_insert_statement user_id=$current_user_id", "user_id=$current_user_id");
#add by kelly
my $sql_hash = {
type => 'sql',
object => {
table => {table1=>"user",},
column => {column1=>"user_id",},
condition => {user_id=>$current_user_id,},
},
};
my $key=Zorpia::MemCache::get_key($sql_hash);
my $query = "SELECT *, user_id AS id FROM user WHERE user_id=?";
my $sth_memc = $dbh->prepare($query);
$sth_memc->execute($current_user_id);
my $user_memc = $sth_memc->fetchrow_hashref();
&Zorpia::MemCache::set($key,$user_memc,21600);