我在 PHP 中有这段代码,将 View 写入文本文件并增加数量。我的问题是:如果两个或更多人使用我的网站并运行 PHP 脚本会怎样?服务器会处理吗?增量会保存到文件中吗?
这是我的代码(如果有帮助的话):
<?php
$clicks = file_get_contents("clicks.txt");
$clicks++;
$fp = fopen("clicks.txt", "w+");
fwrite($fp, $clicks);
fclose($fp);
//give the count to the user
echo "result: $clicks";
?>
最佳答案
首先:这不是我编写点击计数器的方式。
也就是说,100 个用户同时访问您的服务器(初始点击次数为 0)可能会导致记录的数量为 1..100,并且低(= 错误)值很突出。
编辑:实现
我为文本文件、SQLite 和 MySQL 中的文件计数器创建了以下实现
请不要因为我使用 mysql_*() 函数族而责备我——因为代码总是具有启发性,而不是生产力:在专注于手头问题的意义上具有启发性,不是周围的层。
counter-file.php:
<?php
//acquire file handle
$fd=fopen('counter.txt','c+b');
if (!$fd) die("Can't acquire file handle");
//lock the file - we must do this BEFORE reading, as not to read an outdated value
if (!flock($fd,LOCK_EX)) die("Can't lock file");
//read and sanitize the counter value
$counter=fgets($fd,10);
if ($counter===false) die("Can't read file");
if (!is_numeric($counter)) {
flock($fd,LOCK_UN);
die("Value in file '$counter' is not numeric");
}
//increase counter and reconvert to string
$counter++;
$counter="$counter";
//Write to file
if (!rewind($fd)) {
flock($fd,LOCK_UN);
die("Can't rewind file handle");
}
$num=fwrite($fd,$counter);
if ($num!=strlen($counter)) {
flock($fd,LOCK_UN);
die("Error writing file");
}
//Unlock the file and close file handle
flock($fd,LOCK_UN);
fclose($fd);
printf ("Counter is now %05d",$counter);
?>
counter-sqlite.php:
<?php
//counter.sqlite3 was created with
//CREATE TABLE counter (counter NUMERIC)
//INSERT INTO counter VALUES (0)
//Open database
$dsn='sqlite:'.dirname(__FILE__).'/counter.sqlite3';
$db=new PDO($dsn);
if (!$db) die("Can't open SQlite database via DBO");
//Make exclusive
$sql="BEGIN EXCLUSIVE TRANSACTION";
if ($db->exec($sql)===false) die("Error starting exclusive transaction");
//Update counter
$sql="UPDATE counter SET counter=counter+1";
if (!$db->exec($sql)) die("Error inserting into database");
//Read value
$sql="SELECT counter FROM counter";
$result=$db->query($sql);
if (!$result) die("Error querying database");
foreach ($result as $row) $counter=$row['counter'];
//Commit
$sql="COMMIT TRANSACTION";
if (!$db->exec($sql)) die("Error committing to database");
//Print result
printf("Counter is now %05d",$counter);
?>
counter-mysql.php:
<?php
//mysql database was created with
//CREATE TABLE counter (counter INT NOT NULL)
//INSERT INTO counter VALUES (0)
//Open database connection and select database
$db=mysql_pconnect('127.0.0.1','redacted','redacted');
if (!$db) die("Can't open database");
if (!mysql_select_db('redacted', $db)) die("Can't select database");
//Update counter
$sql="UPDATE counter SET counter=counter+1";
$qry=mysql_query($sql,$db);
if (!$qry) die("Error updating database");
//Read value
$sql="SELECT counter FROM counter";
$qry=mysql_query($sql,$db);
if (!$qry) die("Error reading from database");
$counter=mysql_fetch_array($qry,MYSQL_ASSOC);
if (!$counter) die("Error reading result");
//Print result
printf("Counter is now %05d",$counter['counter']);
?>
至于性能:我是正确的。SQLite 实现比其他两个慢 100 倍 - 这是因为我不得不接受,除了 START EXCLUSIVE TRANSACTION 将结束 ab -n 1000 -c 50 http://127.0.0.1/stackoverflow/counter/counter-sqlite.php 的测试,点击次数为 1000 次。
我对 OP 的建议是使用 MySQL 版本 - 它速度快,并且可以在操作系统崩溃时可靠地保存计数器。文件版本具有几乎相同的性能特征,但它很容易被操作系统崩溃破坏。
关于php - 服务器会同时处理两个或多个吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11065212/
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这