我开始玩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。
答案 0 :(得分:3)
我认为您的要求应该根据您的流量来实施。
如果您的流量较低,实施基于锁定的计数器可能不是问题。因为并发访问同一文件的概率非常低,打开,写入和关闭文件需要几毫秒。
另一种解决方案可能是使用memcached,redis或APC缓存机制,并在密钥库中保留一个计数器。
如果您正在考虑每秒几百万次点击,则无法将其托管在单个服务器中。最有可能的是,它使用负载均衡器进行扩展,并托管在不同的区域/服务器中。然后命中计数器应该实现非阻塞服务,如消息队列。如果您对排队点击计数器感兴趣,可以在rabbitmq或activemq
上阅读更多内容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