Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 缓存失效导致高负载_Php_Caching_Memcached_High Load - Fatal编程技术网

Php 缓存失效导致高负载

Php 缓存失效导致高负载,php,caching,memcached,high-load,Php,Caching,Memcached,High Load,让我们假设每秒有10K个请求发送到php脚本 每个请求都在检查memcached(或任何其他缓存存储)中的缓存。如果找到缓存,则一切正常,并返回缓存值。如果找不到缓存,我们将进行慢速SQL查询以填充缓存。这是最常见和最简单的缓存方案: $result = $this->loadFromCache($key); if (empty($result)) { $result = $this->makeSlowSqlQuery(); $this->writeToCach

让我们假设每秒有10K个请求发送到php脚本

每个请求都在检查memcached(或任何其他缓存存储)中的缓存。如果找到缓存,则一切正常,并返回缓存值。如果找不到缓存,我们将进行慢速SQL查询以填充缓存。这是最常见和最简单的缓存方案:

$result = $this->loadFromCache($key);
if (empty($result)) {
    $result = $this->makeSlowSqlQuery();
    $this->writeToCache($key, $result);
}
//do something with $result;
在我们没有太多的请求之前,这个方案很有效。一旦我们有太多的请求,我们就会面临这样的情况:大量的请求在缓存中找不到任何东西,并且会尝试重新填充它。因此,它们都将开始执行缓慢的SQL查询,这将导致高负载影响。解决办法是什么

作为可能的解决方案,我看到了以下场景:发现缓存无效的第一个请求应该创建一些触发器,说明缓存重新填充已经开始,而另一个请求应该等待新的缓存或使用旧的(以前的)版本


您如何解决类似问题?

您基本上想要的是锁定模式:

$lockPrefix = "!lock__";
$result = $this->loadFromCache($key);
if (empty($result)) {
     $sleepLimit = 2000; // 2s timeout
     $sleepCount = 0;
     $cacheBlocked = 0;
     while ($this->loadFromCache($lockPrefix . $key) == 1) {
         // signal that something else is updating the cache
         $cacheBlocked = 1;
         // sleep for 1ms
         usleep(1000);
         // timeout logic...
         $sleepCount++
         if ($sleepCount == $sleepLimit) {
             die("Cache read timeout.");
         }
     }
     if ($cacheBlocked == 1) {
         // something else updated the cache while we were waiting
         // so we can just read that result now
         $result = $this->loadFromCache($key);
     } else {
         $this->writeToCache($lockPrefix . $key, 1); // lock
         $result = $this->makeSlowSqlQuery();
         $this->writeToCache($key, $result);
         $this->writeToCache($lockPrefix . $key, 0); // release
     }
}
其思想是缓存是全局的,因此可以用于跨请求保存锁模式。您实际上是在缓存项中创建一个互斥体,并添加了一点逻辑,以确保只启动一个慢速查询