php 中并发读写文件冲突的解决方案
对于日
IP 不高或者说并发数不是很大的应用,一般不用考虑这些!用一般的文件操作
方法完全没有问题。但如果并发高,在我们对文件进行读写操作时,很有可能多个进程对进
一文件进行操作,如果这时不对文件的访问进行相应的独占,就容易造成数据丢失。
例如:一个在线聊天室(这里假定把聊天内容写入文件),在同一时刻,用户 A 和用户
B 都要操作数据保存文件,首先是 A 打开了文件,然后更新里面的数据,但这里 B 也正好
也打开了同一个文件,也准备更新里面的数据。当
A 把写好的文件保存时,这里其实 B 已
经打开了文件。但当
B 再把文件保存回去时,这里已经造成了数据的丢失,因为这里 B 用
户完全不知道它所打开的文件在它对其进行更改时,
A 用户也更改了这个文件,所以最后
B 用户保存更改时,用户 A 的更新就被会丢失。
对于这样的问题,一般的解决方案时当一进程对文件进行操作时,首先对其它进行加锁,
意味着这里只有该进程有权对文件进行读取,其它进程如果现在读,是完全没有问题,但
如果这时有进程试图想对其进行更新,会遭到操作拒绝,先前对文件进行加锁的进程这时
如果对文件的更新操作完毕,这就释放独占的标识,这时文件又恢复到了可更改的状态。接
下来同理,如果那个进程在操作文件时,文件没有加锁,这时,它就可以放心大胆的对文
件进行锁定,独自享用。
一般的方案会是:
代码如下
:
$fp=fopen('/tmp/lock.txt','w+');
if (flock($fp,LOCK_EX)){
fwrite($fp,"Write something here\n");
flock($fp,LOCK_UN);
}else{
echo 'Couldn\'t lock the file !';
}
fclose($fp);
但在
PHP 中,flock 似乎工作的不是那么好!在多并发情况下,似乎是经常独占资源,
不即时释放,或者是根本不释放,造成死锁,从而使服务器的
cpu 占用很高,甚至有时候
会让服务器彻底死掉。好像在很多
linux/unix 系统中,都会有这样的情况发生。所以使用
flock 之前,一定要慎重考虑。
那么就没有解决方案了吗?其实也不是这样的。如果
flock()我们使用得当,完全可能解决死
锁的问题。当然如果不考虑使用
flock()函数,也同样会有很好的解决方案来解决我们的问题。
经过我个人的搜集和总结,大致归纳了解决方案有如下几种。
方案一:对文件进行加锁时,设置一个超时时间。大致实现如下:
代码如下
:
if($fp=fopen($fileName,'a')){
$startTime=microtime();
do{
$canWrite=flock($fp,LOCK_EX);
if(!$canWrite){
usleep(round(rand(0,100)*1000));
}
}while((!$canWrite)&&((microtime()-$startTime)<1000));