我认为你的要求应该考虑到你的流量来实施。
如果您的流量很低,实施基于锁的计数器可能不成问题。由于并发访问同一文件的概率非常低,打开,写入和关闭文件需要几个毫秒。
另一种解决方案可能是使用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();
}
?>
根据该文档,羊群将阻塞,直到该锁被获取。为什么你建议使用循环(假设一个while循环)? – Kasra
对不起,没有提到:我通常使用flock()和Option LOCK_NB。这给了我避免死锁的机会。例如。人们只能尝试锁定100次然后放弃。 – maxhb