同意文件操作同意文件的问题在于逻辑有些地方不合适,如果多个线程同时写入,在不加锁的情况下,可能导致得到结果不如意,为了安全,和脏读(数据库的词),应该使用排他锁,这就意味着每次只能被一个线程操作。其他线程只能等待,如果超时则会报错。
1 关键函数: 2 fopen() // 打开文件或一个http地址,形成一个文件流 3 flock() // 对文件加锁及解锁 4 fwrite() // 对文件读写操作 5 fclose() // 关闭文件流
1 fopen() resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] ) 2 3 文件打开模式: 4 'r' 只读方式打开,将文件指针指向文件头。 5 'r+' 读写方式打开,将文件指针指向文件头。 6 'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 7 'w+' 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。 8 'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 9 'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。 10 'x' 创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建之。这和给 底层的 open(2) 系统调用指定 O_EXCL|O_CREAT 标记是等价的。 11 'x+' 创建并以读写方式打开,其他的行为和 'x' 一样。
1 flock() bool flock ( resource $handle , int $operation [, int &$wouldblock ] ) 2 3 4 handle 5 文件系统指针,是典型地由 fopen() 创建的 resource(资源)。 6 operation 7 operation 可以是以下值之一: 8 ◦ LOCK_SH取得共享锁定(读取的程序)。 9 ◦ LOCK_EX 取得独占锁定(写入的程序。 10 ◦ LOCK_UN 释放锁定(无论共享或独占)。 11 12 13 如果不希望 flock() 在锁定时堵塞,则是 LOCK_NB(Windows 上还不支持),即遇到有锁不等待,直接报错返回EWOULDBLOCK 14 写法为:$re = flock(lockfd,LOCK_EX|LOCK_NB) 15 有错则返回$re = -1,errno = EWOULDBLOCK
1 fwrite() int fwrite ( resource $handle , string $string [, int $length ] ) 2 3 handle 4 文件系统指针,是典型地由 fopen() 创建的 resource(资源)。 5 string 6 The string that is to be written. 7 length 8 如果指定了 length,当写入了 length 个字节或者写完了 string 以后,写入就会停止,视乎先碰到哪种情况。 9 10 注意如果给出了 length 参数,则 magic_quotes_runtime 配置选项将被忽略,而 string 中的斜线将不会被抽去。 11 12 fwrite() 返回写入的字符数,出现错误时则返回 FALSE 。
1 fclose() bool fclose ( resource $handle ) 2 3 handle 4 文件指针必须有效,并且是通过 fopen() 或 fsockopen() 成功打开的。
通常这样子并不能从根本解决阻塞问题,只能是缓解一下,最好是通过中间件或者reids把请求排成一个队列,保证请求队列不会数据丢失,但是对于写入的数据不是那么重要的,可以用这个方法,直接写入,丢失就丢失了。
在前期调试的时候,可以先用这个方法直接把数据写在文件里,可视化强烈一些,后期可以用mongodb替换文件写入,或者多个文件分类分目录写入,而控制阻塞问题需要使用redis等来控制确保单文件操作的同时,请求不会丢失。