PHP中磁盘缓存清除/大小限制的模式?

PHP中磁盘缓存清除/大小限制的模式?,php,caching,design-patterns,Php,Caching,Design Patterns,我的脚本通过慢速连接获取大量JPEG文件。我将下载的文件存储在本地缓存中并重复使用,直到它们被更改 问题是:如何确保此缓存永远不会超过16Mb(比如)? 我可以在我想要的时候清理它: 计算缓存中所有文件的总大小 删除一些文件,直到它低于16Mb减去我需要的容量 但是如果脚本的两个实例都这样做了呢?两者都确保1Mb是空闲的,然后分别使用1Mb,现在缓存是17Mb。16Mb规则被打破了 我知道我可以制作“惰性缓存”:只要不时清理一下就可以了。但是恶意用户可以触发大量缓存并耗尽磁盘空间。这是一个共享主

我的脚本通过慢速连接获取大量JPEG文件。我将下载的文件存储在本地缓存中并重复使用,直到它们被更改

问题是:如何确保此缓存永远不会超过16Mb(比如)?

我可以在我想要的时候清理它:

  • 计算缓存中所有文件的总大小
  • 删除一些文件,直到它低于16Mb减去我需要的容量
  • 但是如果脚本的两个实例都这样做了呢?两者都确保1Mb是空闲的,然后分别使用1Mb,现在缓存是17Mb。16Mb规则被打破了

    我知道我可以制作“惰性缓存”:只要不时清理一下就可以了。但是恶意用户可以触发大量缓存并耗尽磁盘空间。这是一个共享主机,所以没有人可以这样做

    我想出的唯一解决方案(不好):


    在存储任何内容之前,锁定整个缓存,清理所需空间,存储文件,解锁缓存。为什么不好:我缓存了很多文件,所以进行了很多锁定和清理。慢点。(您如何在PHP中锁定/等待锁定?

    可能我误解了您的意思-这看起来太容易了。如果您没有可用的数据库-read database=具有某种数据格式的文件

    在数据库中创建一个包含以下列的表:文件名、文件大小、文件仍在下载时的标志(true/false)

    当您收到下载文件的新请求时,请锁定此表。计算总和(文件大小)

  • 若小于16MB减去新文件大小,那个么将新条目添加到表中。文件下载后更改标志(在文件下载前/下载后带有lock/unlock的cource)
  • 若更多:查看是否有一些下载的文件,可以在并没有足够可用空间的情况下删除它们,然后将条目添加到表中
  • 如果无法释放足够的内存,请拒绝此请求/等待下载某些文件

  • 在每个案例之后立即解锁表格-每次应仅锁定几毫秒,因此无需等待任何人。

    我不会按照您的规则进行操作,但您可以使用以下方法:

    -

    LOCK_EX-在继续访问时获取文件的独占锁 写作


    在某处创建一个.txt文件,让脚本尝试获取内容。如果有一个脚本已经在运行,它将锁定该文件,因此新脚本将无法访问该文件。如果无法访问该文件,请不要执行缓存代码。

    您可能会使用泄漏的存储桶。您需要存储lasttime(unix时间戳)和bucket(整数)。每次存储内容时,计算自上次保存到缓存以来的时间间隔,从bucket开始以秒为单位递减,然后将bucket加x字节。如果存储桶大于您的容量减去jpeg文件大小,则删除最旧的对象以释放所需空间。

    从远程位置获取文件之前,您知道文件大小吗?如果没有,你可以在获取文件后清理缓存目录。我可以,但这有帮助吗?两个实例每次取1MB,都确保有1MB空闲,都写下1Mb=>2MB。@你自己能解释高速缓存是PHP生成的HTML、源代码、序列化数据、JSON,还是普通静态图像?@ AjReal:只是图像(有时候,其他二进制数据)。@你自己也应该考虑其他像CDAN托管一样的Amazon S3,当然,它比您当前的主机更便宜,也更实惠……这是一个有趣的想法,因为它使锁定更容易,但在其他方面不是一样吗?我仍然每次都必须以独占方式锁定。@他自己:如果独占式锁定只锁定几毫秒,那么它有什么问题?大多数使用MySql的应用程序如果编写正确,就会使用锁。文件系统锁有点糟糕,但大多数操作系统都会这样做。有很多文件需要缓存,所以我认为每次运行清理(也完全锁定)都会引入瓶颈。这不仅仅是几毫秒,因为您正在删除文件并在其中插入文件,而且磁盘IO速度很慢。请重新阅读我的帖子,您在锁定时不会执行任何I/O操作,您只会读取/写入数据库,这应该会立即发生(如果不使用内存数据库,可能是I/O,但它确实很小,在任何磁盘上都会很快)。所有文件都是在锁之外下载的。如果您需要我描述如何删除锁之外的文件,也可以说。当您读/写数据库时,您正在进行文件I/O(除非它是memcached,但不是)。它不是“小”也不是“大”,而是您正在读取的文件的大小。如果您正在从数据库中读取1.5Mb JPEG,则您正在从磁盘中读取1.5Mb的数据。数据库(不是缓存的内存)在这里不会改变任何东西。