在实时网站上只执行一次php脚本

时间:2010-10-21 17:12:10

标签: php

我有一个实时更新功能的脚本。我会把它转移到一个cron工作,但由于一些限制,我宁愿让它活动并在页面加载时调用。

问题在于,当有大量流量时,它并不能正常工作,因为它使用了一些随机和加权数字,所以如果它经常发生一次,结果就不是我们想要的了。 / p>

所以,问题是。有没有办法告诉特定脚本被访问了多少次?并且一次只能限制一次?

谢谢!

3 个答案:

答案 0 :(得分:5)

您正在寻找的技术称为锁定。

最简单的方法是创建一个临时文件,并在操作完成后将其删除。其他进程将查找该临时文件,看它已经存在并消失。

但是,您还需要注意锁定所有者进程崩溃的可能性,并且无法删除锁定。这就是这个简单的任务似乎变得复杂的地方。

基于文件的锁定解决方案

PHP有一个内置的flock()函数,它承诺独立于操作系统的基于文件的锁定功能。 This question有一些关于如何使用它的实用提示。但是,手册页警告说,在某些情况下,flock()在尝试同时获取锁定的多个PHP脚本实例时出现问题。 This question似乎在这个问题上有更高级的答案,但实施起来并不容易。

基于数据库的锁定

this question的作者 - 可能会被flock()的复杂问题吓跑 - 请求其他的,而不是基于文件的锁定技术,并提出MySQL的GET_LOCK()。我从来没有使用它,但它看起来很简单 - 如果你使用mySQL,它可能值得一试。

该死的,如果你想做的话,这个问题是复杂的!有兴趣看看是否有更优雅的东西出现。

答案 1 :(得分:3)

你可以这样做(需要PHP 5):

if(file_get_contents("lock.txt") == "unlocked"){
  // no lock present, so place one
  file_put_contents("lock.txt", "locked");

  // do your processing
  ...

  // remove the lock
  file_put_contents("lock.txt", "unlocked", LOCK_EX);
}
默认情况下,

file_put_contents()会覆盖文件(而不是附加),因此文件的内容应该只是“锁定”或什么都不会。您需要指定LOCK_EX标志,以确保当您尝试写入该文件时,该文件当前未被该脚本的另一个实例打开。

显然,正如@Pekka在他的回答中提到的,如果在放置锁定并将其删除之间发生致命错误(或PHP崩溃,或服务器崩溃等等),这可能会导致问题,因为文件将简单保持锁定。

答案 2 :(得分:1)

使用sql查询启动脚本,该查询测试数据库中的时间戳字段是否超过1天。 如果是 - 写下当前时间戳并执行脚本。

伪sql来表明这个想法:

UPDATE runs SET lastrun=NOW() WHERE lastrun<NOW()-1DAY

(不同的sql server将需要在上面进行不同的更改)

检查已更新的行数以查看此脚本是否获得锁定。 不要使用两个查询 - SELECT和UPDATE,因为它不再是原子。