1

我有一个不寻常的问题,我设法找到了根源。我目前设置在 CentOS Linux 6.3 nginx/1.0.15 PHP 版本 5.3.18 PHP-FPM 5.3.18-1

我有一个 refresh.txt 文件,每次有人发布更新新时间戳时都会写入该文件。我们还让 JS 每 1 秒检查一次时间戳的值。现在的问题是.. 假设 5 个人或更多人同时大喊写入 refresh.txt 文件,它将使用 100% cpu。只是为了写一个时间戳!!

我不知道它为什么这样做..

这是我的php代码。

if(!empty($rf_clear))
    $tb_send = "clear";
else
    $tb_send = time();

// Add flatfile check
$tbcheck = "refresh.txt";
    $tbsend = fopen($tbcheck, 'w');
    $tbtime = $tb_send;
fwrite($tbsend, $tbtime);
fclose($tbsend);

JS

talk_jax.open("GET", boardurl+"/talkbox/refresh.txt?nocache="+nocache);

我该如何解决这个问题或者解决这个问题?任何帮助我都会非常感激。

谢谢。

编辑:仍然没有解决这个问题。有没有办法限制请求?或者有没有更好的方法一起完成这一切。

我已经尝试过 APC 缓存,问题在于它没有足够快地提供 php 文件,所以喊声真的很慢,除非我做错了什么?

apc_store("refresh", time());

JS

talk_jax.open("GET", boardurl+"/talkbox/refresh.php?nocache="+nocache);

我也尝试过使用数据库。提供 php 文件同样太慢了。

4

2 回答 2

3

最好的选择是使用flock()锁定您的文件进行写入 - http://ar2.php.net/flock - 使用循环以实现 Windows 兼容性,因为flock没有阻止选项(在 CentOS 的情况下无效,但无害) .

$max_tries = 5; // don't loop forever
$tbcheck = "refresh.txt";
$tbsend = fopen($tbcheck, 'w');
for ($try=0; $try<$max_tries, $try++){
    if (flock($tbsend, LOCK_EX, true)) {  // acquire an exclusive blocking lock
        fwrite($tbsend, $tb_send);  // write to file
        fflush($tbsend);            // flush output before releasing the lock
        flock($tbsend, LOCK_UN);    // release the lock
        break;                      // exit the loop
    }
    usleep(100);                    // sleep for 100ms if we couldn't get a lock
}
fclose($tbsend);

另一种选择是使用APCmemcached存储一个锁,然后可以从其他 PHP 进程中检查它。假设您memcached的代码如下所示:

$timeout = 5; // set a cache expiration so a broken process doesn't lock forever
$key = "file_locked";
$max_tries = 5; // don't loop forever
for ($try=0; $try<$max_tries, $try++){
    // check to see if there is a lock
    if (!Memcached::get($key)){
        // not locked, so set a lock before processing
        Memcached::set($key, true, $timeout);

        // write to the file
        $tbcheck = "refresh.txt";
        $tbsend = fopen($tbcheck, 'w');
        $tbtime = $tb_send;
        fwrite($tbsend, $tbtime);
        fclose($tbsend);

        // delete the lock
        Memcached::delete($key);

        // exit the loop
        break;
    }
    // locked, pause for 100ms
    usleep(100);
}
于 2012-10-29T23:43:57.530 回答
1

考虑改用 Apc。
apc_store('refresh', time());存储
apc_get('refresh');检索

yum install php-apc

此外,您甚至不必将时间存储在其中。
你可以只存储一个计数器 apc_inc('refresher');来存储
,每次发生变化时都会增加,如果新值高于你以前的值,则检查 js。

于 2012-10-31T14:10:45.527 回答