防止狗堆效应——问题和解决方案
这是Przemek Sobstel 的客座转贴,他认为 dogpile 效应问题没有得到足够的涵盖,尤其是在 PHP 世界中。原文: 防止dogpile效应。
当缓存过期并且网站同时受到大量请求时,就会发生 Dogpile 效应。根据我在大流量网站上工作的经验,这是我认为最好的最佳解决方案。它在野外成功使用并且有效。许多人提到存储两个冗余值 FRESH + STALE,但对于大流量网站来说,它正在扼杀我们的网络。我们认为值得分享我们的解决方案并开始讨论以分享经验。
防止狗堆
在 Web 应用程序中实现缓存似乎很简单。您检查值是否被缓存。如果是,则从缓存中获取缓存值并提供服务。如果不是,则生成新值并将其存储在缓存中以供将来请求使用。就这么简单。
但是,如果值过期然后您收到数百个请求怎么办?它不能再从缓存中提供,因此您的数据库会受到大量试图重新生成该值的进程的影响。数据库收到的请求越多,它们的响应速度就越慢。负载尖峰。直到最终他们可能会倒下。
请参见下图(绿色 - 在缓存中,红色 - 无缓存)。
防止 dogpile 效应归结为只有一个进程(第一个进程)重新生成新值,而其他后续进程从缓存中提供陈旧值,直到它被第一个进程引用。
担心提供过时的数据?好吧,如果您的数据库超载和受苦,提供陈旧数据是您可以拥有的最小的不便。如果重新生成新价值需要很长时间,那么让多个进程(而不是一个)执行此操作将无济于事。它只会增加更多的负载。
狗堆效应——预防/实施
使用信号量锁可以防止 Dogpile 效应。如果值过期,第一个进程获取锁并开始生成新值。所有后续请求都会检查是否已获取锁并提供过时的内容。生成新值后,释放锁。
需要注意的重要一点是,实际上值应该被赋予延长的生命周期,因此它们在过期时不会被物理移除,并且在需要时仍然可以提供。
这是它的详细工作原理。
从缓存存储中获取缓存值。
$value = $this->store->get($key);
$value
是一个 值对象。
检查缓存值是否过期。如果没过期,就上桌。
if ($value && !$value->isStale()) {
return $value->getResult();
}
否则,获取锁,这样只有一个进程重新生成新值。
$lock_acquired = $this->acquireLock($key, $grace_ttl);
如果无法获取锁,则意味着已经有其他进程重新生成它,所以我们只提供当前(过时)值。
if (!$lock_acquired) {
return $value->getResult();
}
否则(已获取锁),重新生成新值。
$result = ...
将重新生成的值保存在缓存存储中。添加宽限期,以便在其他进程需要时可以提供陈旧的结果。
$expiration_timestamp = time() + $ttl;
$value = new Value($result, $expiration_timestamp);
$real_ttl = $ttl + $grace_ttl;
$this->store->set($key, $value, $real_ttl);
释放锁定。
$this->releaseLock($key);
完整实施: https: //github.com/sobstel/metaphore/blob/master/src/Cache.php。
比喻
Metaphore 是一个开源库,用于防止 PHP 应用程序中的 dogpile 效应。它实际上是对 LSDCache的重写,它已成功用于许多高流量生产 Web 应用程序。我只是认为 LSDCache 已经发展成为多用途缓存库,而 metaphore 则力求简单地只做一件事并将其做好。
用法非常简单。
在 composer.json 文件中:
"require": {
"sobstel/metaphore": "dev-master"
}
在您的 PHP 文件中:
use Metaphore\Cache;
// initialize $memcached object (new Memcached())
$cache = new Cache($memcached);
$cache->cache($key, function(){
// generate content
}, $ttl);
更多阅读
- 高可扩展性 - 策略:打破 Memcache Dog Pile
- Memcached - 避免蜂拥而至
- LeaseWeb 实验室 - 避免内存缓存“狗堆”效应
- mysqlnd-qc 满贯防御
- 狗堆效应以及如何使用 Ruby on Rails memcache-client 补丁避免它
- 如何避免 Rails 应用程序中的狗桩效应
- 薄荷缓存
- Varnish Grace 示例
谢谢
感谢 Mariusz Gil 在 2010 年 PHPCon 上关于 Memcached 的演讲——这让我意识到狗堆效应问题——并允许我使用幻灯片中的图片。
南来地,北往的,上班的,下岗的,走过路过不要错过!
======================个性签名=====================
之前认为Apple 的iOS 设计的要比 Android 稳定,我错了吗?
下载的许多客户端程序/游戏程序,经常会Crash,是程序写的不好(内存泄漏?刚启动也会吗?)还是iOS本身的不稳定!!!
如果在Android手机中可以简单联接到ddms,就可以查看系统log,很容易看到程序为什么出错,在iPhone中如何得知呢?试试Organizer吧,分析一下Device logs,也许有用.