Php 当缓存过期时,如何防止应用程序对数据库进行DDoS攻击?

Php 当缓存过期时,如何防止应用程序对数据库进行DDoS攻击?,php,mysql,codeigniter,caching,memcached,Php,Mysql,Codeigniter,Caching,Memcached,我们有一个高流量的网站,很像StackOverflow,在memcache中有对象缓存。该网站是用PHP(CodeIgniter)和MySQL构建的 每次作为每个页面加载一部分的缓存对象上的TTL(生存时间)过期时,此时的所有页面加载都会导致对数据库的查询,从而有效地对数据库执行DDOS 是否有某种方式只让一个页面加载重新获取数据,而让其他页面加载等待第一个页面加载更新缓存 我的第一个想法是使用随机化器,让一些页面加载获取数据,让其他页面在重新检查缓存之前等待一秒钟。但是肯定有更好的方法。如果您

我们有一个高流量的网站,很像StackOverflow,在memcache中有对象缓存。该网站是用PHP(CodeIgniter)和MySQL构建的

每次作为每个页面加载一部分的缓存对象上的TTL(生存时间)过期时,此时的所有页面加载都会导致对数据库的查询,从而有效地对数据库执行DDOS

是否有某种方式只让一个页面加载重新获取数据,而让其他页面加载等待第一个页面加载更新缓存


我的第一个想法是使用随机化器,让一些页面加载获取数据,让其他页面在重新检查缓存之前等待一秒钟。但是肯定有更好的方法。

如果您可以控制后台任务,例如cronjobs,那么您可以安排在要求的时间之前完成工作并获取数据,以便最近的数据永远不会从缓存中出来


例如,您可以让作业每20分钟运行一次(或者每分钟运行一次),更新缓存的值。当该作业运行时,不需要其他数据库查询来获取数据。

您可以从以下代码中使用我的算法:

  • 读键和TTL
  • 如果TTL很小(例如,小于5秒 例如),尝试锁定特殊钥匙(不是您正在阅读的钥匙),如 “_update.{name_of_key}”
  • 如果锁定成功-计算(或 读取)新值并刷新缓存
  • 释放更新密钥

  • 因此,只有一个进程将从DB中读取新值。

    为了澄清我的答案,我将编写一些代码来说明我的想法(无论如何,这可能是一个解决方案……):


    所涉及的唯一风险是在同一时间出现两次页面点击,这可能会使缓存重新生成两次。这是非常不可能的,但如果发生这种情况,至少所有其他请求仍在等待

    +1用于缓存考虑!但是,这会导致多个额外的查询,因为您会让其他请求轮询数据库,直到您将页面标记为“重新链接到缓存”为止。请参见。@eggyal这里有很多有趣的想法,谢谢。这是个好主意。实际上,我们已经在为页面加载时间太长而无法接受的请求执行此操作。事实上,我可以让一个cronjob定期检查每个缓存项的TTL,并提前几秒钟刷新它们。谢谢。缓存锁定的概念对我来说是新概念。我会看看是否可以将此解决方案应用到我们的应用程序中。谢谢,如果我理解正确,这与其他人所说的缓存锁定基本相同。
    if ($this->cacheExpired()){
        if (!$this->isMarkedAsRegenerating())
        {
             $this->markAsRegenerating();              //..ing
             $this->regenerateCache();
             $this->markAsCacheRegenerated();          //..ed
        } else {
             while ( $this->isMarkedAsRegenerating() )
             {
                   sleep(1); //sleep 1 second to decrease database-queries, we are preventing a DDOS you know...
             }
        }
    }
    
    $this->output(); //at this point, we always have a cached version of the page