perl - 缓存和避免 Cache Stampedes - 多个同时计算

标签 perl caching

我们想要缓存一个非常昂贵的计算。所以我们做类似的事情:

my $result = $cache->get( $key );

unless ($result) {
    $result = calculate( $key );
    $cache->set( $key, $result, '10 minutes' );
}

return $result;

现在,在 calculate($key) 期间,在我们将结果存储到缓存中之前,还有其他几个请求进来,它们也开始运行 calculate($key) ,并且系统性能受到影响,因为许多进程都在计算相同的东西。

想法:让我们在缓存中放置一个正在计算一个值的标志,所以其他请求只是等待那个计算完成,所以他们都使用它。就像是:
my $result = $cache->get( $key );

if ($result) {
    while ($result =~ /Wait, \d+ is running calculate../) {
        sleep 0.5;
        $result = $cache->get( $key );
    }
} else {
    $cache->set( $key, "Wait, $$ is running calculate()", '10 minutes' );
    $result = calculate( $key );
    $cache->set( $key, $result, '10 minutes' );
}


return $result;

现在,这开辟了一个全新的蠕虫 jar 头。如果 $$ 在设置缓存之前死了怎么办。如果,如果...所有这些都可以解决,但是由于 CPAN 中没有任何内容这样做(CPAN 中的一切都有),我开始想:

有更好的方法吗?是否有特殊原因,例如Perl 的 CacheCache::Cache类不提供这样的机制吗?有没有我可以使用的经过验证的真实模式?

理想的情况是一个 CPAN 模块,它的 debian 包已经处于挤压状态或 eureka 时刻,在那里我看到了我的方式的错误...... :-)

编辑:我已经知道这被称为 Cache stampede并更新了问题的标题。

最佳答案

flock()它。

由于您的工作进程都在同一个系统上,您可能可以使用良好的老式文件锁定来序列化昂贵的 calculate() ionic 。作为奖励,这种技术出现在几个核心文档中。

use Fcntl qw(:DEFAULT :flock);    # warning:  this code not tested

use constant LOCKFILE => 'you/customize/this/please';

my $result = $cache->get( $key );

unless ($result) {
    # Get an exclusive lock
    my $lock;
    sysopen($lock, LOCKFILE, O_WRONLY|O_CREAT) or die;
    flock($lock, LOCK_EX) or die;

    # Did someone update the cache while we were waiting?
    $result = $cache->get( $key );

    unless ($result) {
        $result = calculate( $key );
        $cache->set( $key, $result, '10 minutes' );
    }

    # Exclusive lock released here as $lock goes out of scope
}

return $result;

好处: worker 死亡会立即释放$lock .

风险:LOCK_EX 可以永远阻塞,而且是很长的时间。避免 SIGSTOP,也许对 alarm() 感到满意.

扩展:如果不想全部序列化calculate()调用,但只是所有调用相同的 $key或一些 key ,您的 worker 可以 flock() /some/lockfile.$key_or_a_hash_of_the_key .

关于perl - 缓存和避免 Cache Stampedes - 多个同时计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10710587/

相关文章:

perl - 无法在 ~/modules/Log/Syslog/Constants.pm 第 28 行使用未定义的值作为 ARRAY 引用

regex - Perl正则表达式从任意集合中查找字符

python - Sha256与pip的不匹配安装在新的docker镜像上

java - 我可以通过它占用的内存量来限制 HashMap 吗?

java - 防止 Spring 尝试读取旧的资源流

ubuntu - 在 github actions ubuntu-latest 上收到 "Cache not found for input keys: cache-playwright-linux-1.20.0"

perl - 使用反引号时转义空格

perl - 如何调用绑定(bind)变量的方法?

multithreading - Perl线程缓慢消耗内存

php - Memcached vs APC 我应该选择哪一个?