设置:高流量网站和我们想要显示的图片网址列表。我们有一个图像点,图像URL集中的每个项目都具有当天的目标显示百分比。例如:
因为交通量每天都在变化,所以我在1000块内完成百分比。图像也需要随机挑选,但仍能准确地适应分布。
问题:我已经在memcache中实现了POC代码,但我对数据的存储方式感到不舒服(多个哈希键由“主记录”和元数据映射)。如果内存缓存服务器出现故障,这也需要能够回退到数据库。我也担心主记录的并发问题。
有没有更简单的方法来实现这一目标?也许是一个快速的mysql查询或更好的方法将memcache带入其中?
由于
答案 0 :(得分:1)
你可以做你所说的,预先生成一个1000个值的块,指向你将返回的图像:
$distribution = "011022201111202102100120 ..." # exactly evenly distributed
然后将该块存储在MySQL和memcache中,并使用另一个密钥(在MySQL和memcache中)保存上述字符串的当前索引值。每当图像脚本被命中时,都会增加memcache中的值。如果memcache发生故障,请转到MySQL(UPDATE,然后选择SELECT;可能有更好的方法来执行此操作)。
为了使memcache和MySQL保持同步,你可以让cron作业将当前索引值从memcache复制到MySQL。你会失去一些准确性但在这种情况下可能并不重要。
您可以在MySQL和memcache中存储多个发行版,并拥有指向当前活动发行版的另一个键。这样你就可以预生成未来的图像块。当索引超出分布时,脚本会递增密钥并转到下一个密钥。
大致是:
function FetchImageFname( )
{
$images = array( 0 => 'image1.jpg', 1 => 'image2.jpg', 2 => 'image3.jpg' );
$distribution = FetchDistribution( );
$currentindex = FetchCurrentIndex( );
$x = 0;
while( $distribution[$currentindex] == '' && $x < 10 );
{
IncrementCurrentDistribKey( );
$distribution = FetchDistribution( );
$currentindex = FetchCurrentIndex( );
$x++;
}
if( $distribution[$currentindex] == '' )
{
// XXX Tried and failed. Send error to central logs.
return( $images[0] );
}
return( $distribution[$currentindex] );
}
function FetchDistribution( )
{
$current_distib_key = FetchCurrentDistribKey( );
$distribution = FetchFromMemcache( $current_distrib_key );
if( !$distribution )
$distribution = FetchFromMySQL( $current_distrib_key );
return $distribution;
}
function FetchCurrentIndex( )
{
$current_index = MemcacheIncrement( 'foo' );
if( $current_index === false )
$current_index = MySQLIncrement( 'foo' );
return $current_index;
}
..等等这个函数有点臭,但我想你会明白的。当memcache服务器再次备份时,您可以将MySQL中的数据复制回memcache,并立即重新激活。
答案 1 :(得分:0)
对数据库的命中很可能会花费更长的时间,所以我会坚持使用memcache。使用MySQL比使用memcache更容易出现并发问题。 memcache可以更好地处理大量请求,如果服务器出现故障,这将是您在高流量网站上最不用担心的问题。
如果你给我们更多细节,也许MySQL专家可以在这里使用一个好的查询结构。