background image

    $success=fclose($fp[0]);
    clearstatcache();
    $tempfilename=$dir_fileopen.'/'.$fp[2].md5($fp[1]);
    if((@filemtime($fp[1])==$fp[3])||($fp[4]==true&&!file_exists($fp[1]))||$fp[5]==true){
        rename($tempfilename,$fp[1]);
    }else{
        unlink($tempfilename);
  //说明有其它进程 在操作目标文件,当前进程被拒绝
        $success=false;
    }
    return $success;
}
$fp=cfopen('lock.txt','a+');
cfwrite($fp,"welcome to beijing.\n");
fclose($fp,'on');

对于上面的代码所使用的函数,需要说明一下:

1)rename();重命名一个文件或一个目录,该函数其实更像 linux 里的 mv。更新文件或者

目录的路径或名字很方便。但当我在

window 测试上面代码时,如果新文件名已经存在,会

给出一个

notice,说当前文件已经存在。但在 linux 下工作的很好。

2)clearstatcache();清除文件的状态.php 将缓存所有文件属性信息,以提供更高的性能,

但有时,多进程在对文件进行删除或者更新操作时,

php 没来得及更新缓存里的文件属性,

容易导致访问到最后更新时间不是真实的数据。所以这里需要使用该函数对已保存的缓存进
行清除。

 

方案三:对操作的文件进行随机读写,以降低并发的可能性。在对用户访问日志进行记

录时,这种方案似乎被采用的比较多。先前需要定义一个随机空间,空间越大,并发的的可
能性就越小,这里假设随机读写空间为

[1-500],那么我们的日志文件的分布就为 log1~到

log500 不等。每一次用户访问,都将数据随机写到 log1~log500 之间的任一文件。在同一时刻,

2 个进程进行记录日志,A 进程可能是更新的 log32 文件,而 B 进程呢?则此时更新的

可能就为

log399.要知道,如果要让 B 进程也操作 log32,概率基本上为 1/500,差不多约等于

零。在需要对访问日志进行分析时,这里我们只需要先将这些日志合并,再进行分析即可。
使用这种方案来记录日志的一个好处时,进程操作排队的可能性比较小,可以使进程很迅
速的完成每一次操作。

方案四:将所有要操作的进程放入一个队列中。然后专门放一个服务完成文件操作。队

列中的每一个排除的进程相当于第一个具体的操作,所以第一次我们的服务只需要从队列
中取得相当于具体操作事项就可以了,如果这里还有大量的文件操作进程,没关系,排到
我们的队列后面即可,只要愿意排,队列的多长都没关系。

对于以前几种方案,各有各的好处!大致可能归纳为两类:

1)需要排队(影响慢)比如方案一、二、四

2)不需要排队。(影响快)方案三

    在设计缓存系统时,一般我们不会采用方案三。因为方案三的分析程序和写入程序是不同
步的,在写的时间,完全不考虑到时候分析的难度,只管写的行了。试想一下,如我们在更
新一个缓存时,如果也采用随机文件读写法,那么在读缓存时似乎会增加很多流程。但采取
方案一、二就完全不一样,虽然写的时间需要等待(当获取锁不成功时,会反复获取),但
读文件是很方便的。添加缓存的目的就是要减少数据读取瓶颈,从而提高系统性能。