in PHP, Flock seems to be not working so well! In the case of multiple concurrency, it seems that the resources are often exclusive, not released immediately, or not released at all, resulting in a deadlock, which makes the server CPU occupied very high, and sometimes the server is completely dead. It seems that in many Linux/unix systems, this happens. So before using flock, be sure to consider carefully.
If Flock () is used properly, it is possible to solve the deadlock problem. Of course, if you do not consider the use of the flock () function, there will also be a good solution to solve our problem. Some of the solutions are summarized as follows.
Scenario One: When the file is locked, set a time-out. The approximate implementation is as follows:
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); if ($canWrite) { fwrite ($fp, $dataToSave);} fclose ($FP);}
Timeout set to 1ms, if there is no lock in time, it is repeatedly obtained, directly to the file operation right, of course. If the time-out limit is reached, it is necessary to exit immediately and let the other process do the lock.
Scenario Two: Do not use the Flock function to borrow temporary files to resolve read-write conflicts. The general principle is as follows:
(1) Consider a copy of the file that needs to be updated to our temp file directory, save the last modification time of the file to a variable, and take a random, non-repeatable file name for the temporary file.
(2) when the temporary file is updated, the last update time of the original file is checked for consistency with the time previously saved.
(3) If the last modification time is consistent, the modified temporary file is renamed to the original file, in order to ensure that the file status synchronization update, so you need to clear the file status.
(4) However, if the last modification time is consistent with the previous save, this indicates that during this period the original file has been modified, then the temporary file needs to be deleted and then returned false, stating that there are other processes in the file. The
Implementation code is as follows:
$dir _fileopen= ' tmp '; function Randomid () {return time (). substr (MD5 (Microtime ()), 0,rand (5,12));} function Cfopen ($filename, $mode) {global $dir _fileopen; Clearstatcache (); do{$id =md5 (Randomid (rand (), TRUE)); $tempfilename = $dir _fileopen. ' /'. $id. MD5 ($FILENAME); } while (File_exists ($tempfilename)); if (file_exists ($filename)) {$newfile =false; Copy ($filename, $tempfilename); }else{$newfile =true; } $fp =fopen ($tempfilename, $mode); return $fp? Array ($fp, $filename, $id, @filemtime ($filename)): false;} function Cfwrite ($fp, $string) {return fwrite ($fp [0], $string);} function Cfclose ($fp, $debug = ' off ') {global $dir _fileopen; $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); Indicates that there are other processes in the operation target file, the current process is rejected $success =false; } return $success;} $fp =cfopen (' lock.txt ', ' A + '), Cfwrite ($fp, "Welcome to beijing.\n"), fclose ($fp, ' on ');
For the functions used in the above code, you need to explain:
(1) rename (); Rename a file or a directory, which is actually more like a MV in Linux. It is convenient to update the path or name of the file or directory. But when I test the above code in window, if the new file name already exists, it gives a notice that the current file already exists. But it works well under Linux.
(2) Clearstatcache (); Clears the status of the file. PHP caches all file attribute information to provide higher performance, but sometimes when a multi-process deletes or updates a file, PHP does not have time to update the file attributes in the cache, which can lead to access to the last update date that is not real data. So you need to use this function to clear the saved cache.
Scenario Three: The operation of the file random read and write to reduce the likelihood of concurrency.
This scenario seems to be more widely used when logging user access logs. Before the need to define a random space, the larger the space, the more likely the likelihood of concurrency, where random read and write space is assumed to be [1-500], then our log file distribution is log1~ to log500 range. Each time a user accesses, the data is randomly written to any file between log1~log500. At the same time, there are 2 processes logging, the A process may be the updated LOG32 file, and the B process? The update may be log399 at this point. You know, if you want the B process to operate the LOG32, the probability is basically 1/500, almost equal to zero. When the access log needs to be analyzed, we just need to merge the logs before analyzing them. When you use this scenario to record one benefit of logging, process operations are less likely to be queued, allowing the process to complete each operation very quickly.
Scenario Four: Put all the processes you want to manipulate into one queue. then dedicate a service to complete the file operation. Each of the excluded processes in the queue is equivalent to the first specific operation, so the first time our service only needs to get the equivalent of the actual operation from the queue, if there are a lot of file operation process, it's OK, to queue up behind us, as long as willing to platoon, queue of how long it doesn't matter.
For several previous scenarios, each has its own benefits! It may be summed up in two categories:
(1) need to queue (slow impact) such as scenario one, two or four
(2) do not need to queue. (Fast impact) scenario three
When designing a caching system, we generally do not adopt scenario three. Because the analysis program of scenario three and the writer is not synchronized, at the time of writing, completely regardless of the time to analyze the difficulty, just write the line. Imagine that when we update a cache, if we also take random file reading, it seems to be a lot more process to read the cache. However, the adoption of scenario one or two is completely different, although the write time needs to wait (when the acquisition lock is not successful, will be repeatedly acquired), but read the file is very convenient. The purpose of adding a cache is to reduce the data read bottleneck, which improves system performance.