sobstel / metaphore
使用信号量进行PHP缓存击穿防御,以防止击狗效应(也称为覆盖更新或羊群效应)。
Requires
- php: >=8.2
- predis/predis: >=2.0.3
Suggests
- ext-memcache: Required for MemcacheStore
- ext-memcached: Required for MemcachedStore
- predis/predis: Required for PredisStore
This package is not auto-updated.
Last update: 2024-09-21 14:12:13 UTC
README
使用信号量进行PHP缓存击穿防御,以防止击狗效应(也称为覆盖更新、羊群效应或Slashdot效应)。
问题:当网站尝试重新生成相同内容并击中数据库时,同时有太多请求,例如缓存过期时。
解决方案:第一个请求生成新内容,而所有后续请求在第一次请求刷新之前都从缓存获取(陈旧)的内容。
阅读 http://www.sobstel.org/blog/preventing-dogpile-effect/ 了解更多详情。
安装
在 composer.json 文件中
"require": {
"sobstel/metaphore": "2.0.*"
}
或直接 composer require sobstel/metaphore
用法
use Metaphore\Cache; use Metaphore\Store\MemcachedStore; // initialize $memcached object (new Memcached()) $cache = new Cache(new MemcachedStore($memcached)); $cache->cache('key', function() { // generate content }, 30);
公共API(方法)
-
__construct(ValueStoreInterface $valueStore, LockManager $lockManager = null)
-
cache($key, callable $callable, [$ttl, [$onNoStaleCacheCallable]])
- 返回结果 -
delete($key)
-
getValue($key)
- 返回值对象 -
setResult($key, $result, Ttl $ttl)
- 设置结果(不使用抗击狗效应机制) -
onNoStaleCache($callable)
-
getValueStore()
-
getLockManager()
值存储与锁存储
缓存值和锁可以由不同的存储处理。
$valueStore = new Metaphore\MemcachedStore($memcached); $lockStore = new Your\Custom\MySQLLockStore($connection); $lockManager = new Metaphore\LockManager($lockStore); $cache = new Metaphore\Cache($valueStore, $lockManager);
默认情况下 - 如果没有传递第二个参数给Cache构造函数 - 值存储用作锁存储。
示例用例可能是使用自定义MySQL GET_LOCK/RELEASE_LOCK进行锁操作,同时使用内置的Memcached存储来存储值。
生存时间
您可以传递简单的整数值...
$cache->cache('key', callback, 30); // cache for 30 secs
...或使用更高级的 Metaphore\TTl
对象,它让您控制宽限期和锁生存时间。
// $ttl, $grace_ttl, $lock_ttl $ttl = new Ttl(30, 60, 15); $cache->cache('key', callback, $ttl);
$ttl
- 正常缓存时间(以秒为单位)$grace_ttl
- 宽限期,允许在生成新内容的同时提供陈旧内容的时间(以秒为单位),类似于HTTP的stale-while-revalidate,默认为60秒$lock_ttl
- 锁定时间,防止其他请求生成相同内容的时间,默认为5秒
将Ttl值添加到当前时间戳(time() + $ttl
)。
无陈旧缓存
在罕见情况下,当缓存过期且没有可用的陈旧(之前生成)内容时,所有请求都将开始生成新内容。
您可以添加监听器来捕获此情况
$cache->onNoStaleCache(function (NoStaleCacheEvent $event) { Logger::log(sprintf('no stale cache detected for key %s', $event->getKey())); });
您还可以影响返回的值
$cache->onNoStaleCache(function (NoStaleCacheEvent $event) { $event->setResult('new custom result'); });
测试
运行所有测试:phpunit
。
如果没有安装memcached或redis:phpunit --exclude-group=notisolated
或 phpunit --exclude-group=memcached,redis
。