PHP如何同时管理请求
今天我想知道PHP是如何同时处理请求的。由于PHP可以同时处理多个请求,我考虑了PHP脚本中可能存在的安全漏洞或bug,我只是想知道我是否有点太害怕 因此,在同时有100个请求的情况下,apache被配置为将它们转发到PHP。PHP将如何处理以下示例(我在一些实际应用程序中看到的所有示例都是这样的) 所有的例子都是相似的。(我不寻求更好的方法来解决这些案例)PHP如何同时管理请求,php,multithreading,security,Php,Multithreading,Security,今天我想知道PHP是如何同时处理请求的。由于PHP可以同时处理多个请求,我考虑了PHP脚本中可能存在的安全漏洞或bug,我只是想知道我是否有点太害怕 因此,在同时有100个请求的情况下,apache被配置为将它们转发到PHP。PHP将如何处理以下示例(我在一些实际应用程序中看到的所有示例都是这样的) 所有的例子都是相似的。(我不寻求更好的方法来解决这些案例) 示例1:创建缓存 <?php if (!file_exists('my_cache.txt')) { // do some
示例1:创建缓存
<?php
if (!file_exists('my_cache.txt')) {
// do something slow (taking a second or so)
file_put_contents('my_cache.txt', $cache);
}
<?php
writeItemToDatabase($myItem);
if (countAllItemsInDatabase() > 100) {
$items = readAllItemsFromDatabase();
deleteAllItemsFromDatabase();
// Process items
}
<代码> 你考虑的东西,代码样本是“强”>不是线程安全< /强>。这不是PHP的问题,而是并发性的一般问题 解决办法是:
- 对于像示例1和示例2这样的文件操作,请使用文件锁
- 对于像货币交易这样的操作,请使用数据库交易或最终使用表锁
您提到的这种信号量不是一个好的解决方案。例如,在数据库级别,db引擎可以锁定/解锁单个表甚至行,这与“在那段代码上锁定整个服务器”相比是非常有效的 Memcache
cas()
或add()
函数对于文件锁定的实现非常方便
Add()
仅当服务器上还不存在某个键时,才使用该键存储变量<代码>Cas()还执行“检查并设置”操作。
基于这些操作之一设计信号量是非常容易的 对不起我的英语
首先,我将描述一些一般特性:
$semaphore->lock()
//做些危险的事
$semaphore->unlock();
updatethreadingset\u lock=1,其中id=1和\u lock 1代码>
注意:和_lock1
防止记录在已锁定时锁定,因此您可以确定记录是否被受影响的机制锁定
<?php
// connect
mysql_connect('localhost','root','root');
mysql_selectdb('testing');
// get info
$res = mysql_query('select * from threading where id = 1;');
$row = mysql_fetch_assoc($res);
print_r($row); // debug
if($row['val']>=70){
sleep(5); // emulate long-long operation =)
// try to lock
mysql_query('update threading set _lock = 1 where id = 1 AND _lock <> 1 ;'); // _lock <> 1 - very IMPORTANT!
sleep(5); // emulate long-long operation =)
$affected_rows = mysql_affected_rows();
if($affected_rows!=1){
// lock failed - locked by another instance
echo '<br> LOCKED!';
}else{
// lock succeed
mysql_query('update threading set val = val-70 where id = 1;');//something dangerous
mysql_query('update threading set _lock = 0 where id = 1;'); // UNLOCK!
}
}
// view result
$res = mysql_query('select * from threading where id = 1;');
$row2 = mysql_fetch_assoc($res);
echo '<br>';
print_r($row2);
// disconnect
mysql_close();
需要“SafeCache.class.php”;
//获取非阻塞独占锁
$safe=新的SafeCache(“独占锁定id”);
如果($safe->getExclusive()){
打印“我们现在拥有独占锁
”;
// ...
打印“释放锁
”;
$safe->doneeExclusive();
}
另外,请看其他安全缓存生成的示例。
这是一个真正的问题。(i) PHP有一个内置的flock
函数,用于(ii)PHP序列化会话(iii)数据库有自己的并发管理机制。
<?php
$semaphore->lock();
// Do something dangerous
$semaphore->unlock();
<?php
$fname = 'test.txt';
$file = fopen($fname, 'a+');
sleep(5); // long operation
if(flock($file,LOCK_EX|LOCK_NB )){// we get file lock - $semaphore->lock();
sleep(5); // long operation
fputs($file, "\n".date('d-m-Y H:i:s')); //something dangerous
echo 'writed';
flock($file,LOCK_UN ); // release lock - $semaphore->unlock();
}else{
// file already locked
echo 'LOCKED';
}
fclose($file);
CREATE TABLE `threading` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`val` INT(10) NOT NULL,
PRIMARY KEY (`id`)
)COLLATE='utf8_general_ci'
ENGINE=InnoDB
ALTER TABLE `threading`
ADD COLUMN `_lock` BIT NOT NULL AFTER `val`;
<?php
// connect
mysql_connect('localhost','root','root');
mysql_selectdb('testing');
// get info
$res = mysql_query('select * from threading where id = 1;');
$row = mysql_fetch_assoc($res);
print_r($row); // debug
if($row['val']>=70){
sleep(5); // emulate long-long operation =)
// try to lock
mysql_query('update threading set _lock = 1 where id = 1 AND _lock <> 1 ;'); // _lock <> 1 - very IMPORTANT!
sleep(5); // emulate long-long operation =)
$affected_rows = mysql_affected_rows();
if($affected_rows!=1){
// lock failed - locked by another instance
echo '<br> LOCKED!';
}else{
// lock succeed
mysql_query('update threading set val = val-70 where id = 1;');//something dangerous
mysql_query('update threading set _lock = 0 where id = 1;'); // UNLOCK!
}
}
// view result
$res = mysql_query('select * from threading where id = 1;');
$row2 = mysql_fetch_assoc($res);
echo '<br>';
print_r($row2);
// disconnect
mysql_close();
require "SafeCache.class.php";
// get non blocking exclusive lock
$safe = new SafeCache("exclusive_lock_id");
if ( $safe->getExclusive() ) {
print "we have exclusive lock now<br>";
// ...
print "releasing the lock<br>";
$safe->doneExclusive();
}