PHP多个客户端访问相同的文件

时间:2015-12-14 06:37:12

标签: php hitcounter

我开始玩PHP,看到这个代码片段应该是网页的点击计数器:

for (var key in data)
 {
    //alert(data[key]["type"] + data[key]["id"] + data[key]["message"]);
    //$str = $str+;
    $(".notiDiv").append('<div class="row" style="margin: 1px">\n\<div class="col - sm - 8">\n\<a href="#">' user have created a meeting'</a>\n\</div>\n\<div class="form - group col - sm - 4 text - right"  >\n\<a><span class=" glyphicon glyphicon - ok"></span></a>\n\<a><span class=" glyphicon glyphicon - remove"></span></a>\n\</div>\n\</div>\n');
 }
<div class="dropdown-menu dropdown-menu-custom " >
    <div class="notiDiv">

    </div>
</div></li>

根据我读到的内容,可以在服务器上同时运行多个请求。因此,他们有可能同时访问此文件/* counter */ //opens countlog.txt to read the number of hits $datei = fopen("/countlog.txt","r"); $count = fgets($datei,1000); fclose($datei); $count=$count + 1 ; echo "$count" ; echo " hits" ; echo "\n" ; // opens countlog.txt to change new hit number $datei = fopen("/countlog.txt","w"); fwrite($datei, $count); fclose($datei); (正确吗?)。如果是这样,这段代码对繁忙的网站不起作用(对吗?)。如何更改此代码以使其适用于繁忙的网站?你可以在多个请求之间共享的PHP中使用锁吗?

PS:问题不在于反击。如果可能,请避免在答案中使用SQL。

2 个答案:

答案 0 :(得分:3)

我认为您的要求应该根据您的流量来实施​​。

如果您的流量较低,实施基于锁定的计数器可能不是问题。因为并发访问同一文件的概率非常低,打开,写入和关闭文件需要几毫秒。

另一种解决方案可能是使用memcached,redis或APC缓存机制,并在密钥库中保留一个计数器。

如果您正在考虑每秒几百万次点击,则无法将其托管在单个服务器中。最有可能的是,它使用负载均衡器进行扩展,并托管在不同的区域/服务器中。然后命中计数器应该实现非阻塞服务,如消息队列。如果您对排队点击计数器感兴趣,可以在rabbitmqactivemq

上阅读更多内容

RabbitMQ和ActiveMQ支持以下协议和许多其他协议,你可以找到许多php客户端库来连接这些协议。

几个代码示例

使用APC作为计数器

<?php
apc_add('counter', 0);
echo apc_inc('counter')
?>

使用Memcached

<?php
$m = new Memcached();
$m->addServer('localhost', 11211);

$m->add('counter', 0);
$m->increment('counter');
?>

RabbitMQ和php-amqplib

composer.json

{
    "require": {
        "videlalvaro/php-amqplib": "2.5.*"
    }
}

$ composer.phar install

<?php
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$channel->queue_declare('counter', false, false, false, false);

$callback = function($msg) {
  // $msg->body has the content of the message
  // counter update implementation goes here
};

$channel->basic_consume('counter', '', false, true, false, false, $callback);

while(count($channel->callbacks)) {
    $channel->wait();
}
?>

答案 1 :(得分:0)

您可以使用flock()获取文件的独占锁定,请参阅http://php.net/manual/en/function.flock.php

$fp = fopen("/tmp/lock.txt", "r+");

if (flock($fp, LOCK_EX)) {
    $datei = fopen("/countlog.txt","r");
    $count = fgets($datei,1000);

    $count=$count + 1 ;
    echo "$count" ;
    echo " hits" ;
    echo "\n" ;

    ftruncate($fp, 0);
    fwrite($fp, $count);
    fflush($fp);
    flock($fp, LOCK_UN);
} else {
    echo "Could not lock file!";
}

fclose($fp);

也许你应该使用usleep()构建一个等待成功锁定的循环,以避免主动等待:http://php.net/manual/en/function.usleep.php