Crond script execution concurrency conflicts,
In a scheduled task, you will occasionally see repeated executions:
For example, an example of a scheduled task in our company is as follows:
*/2 * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testOne >/dev/null 2>&1*/2 * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testTwo >/dev/null 2>&1
This is a task executed once every two minutes. It cannot be guaranteed that the process that is enabled can be completely executed and shut down within two minutes. If the process has been accumulated, the system resources may be exhausted, this causes system downtime.
Example:
Create the test. php file with the following code:
<?phpsleep(70);?>
Add a scheduled task:
*/1 * * * * root cd /home/ganjincheng;php test.php
Wait for execution, Accumulation
root 26722 0.0 0.0 9232 1064 ? Ss 12:05 0:00 /bin/sh -c cd /home/ganjincheng;php test.phproot 26744 0.0 0.0 112304 8840 ? S 12:05 0:00 php test.phproot 29102 0.0 0.0 9232 1060 ? Ss 12:06 0:00 /bin/sh -c cd /home/ganjincheng;php test.phproot 29116 0.1 0.0 112304 8840 ? S 12:06 0:00 php test.phproot 29906 0.0 0.0 103320 904 pts/3 S+ 12:06 0:00 grep test.php
Solution 1: Control concurrency in code
This method is to transform the code. Determines whether a process is executed. The following code:
<?php $lockfile = '/tmp/mytest.lock'; if(file_exists($lockfile)){ exit(); }file_put_contents($lockfile, date("Y-m-d H:i:s")); sleep(70); unlink($lockfile); ?>
This method of determining whether a file does not exist poses a problem. That is, the program may not be executed until the end, that is, the mytest. lock file created earlier has not been deleted. This will cause the program to fail to run normally.
Second, database Concurrency Control
You can transfer the first scheme to redis and memache for key value judgment.
If the scheduled task is to access the database, you can lock the table. Occasionally, we can use the uniqueness of the unique index and the joint index to avoid repeated inserts.
Third, determine whether a process exists
Example:
$ Fp = popen ("ps aux | grep 'test. php' | wc-l "," r "); $ proc_num = fgets ($ fp); if ($ proc_num> 3) {// note the reason why the number of processes is greater than 3. After you perform the operation, you will understand exit;} sleep (70 );
The disadvantage of this method is that the ps command must be accurate. Avoid counting the processes that are not executing the test. php script. For example:
Run vim to open the test. php file. The preceding command may be incorrectly used for statistics. So when we accidentally open the test. php file in vim, it cannot be executed.
Fourth, use the linux flock command
Let linux help us determine. The flock command provides the file lock function. The command parameters are as follows:
[root@qkzj_Multi-Purpose_1A_113.107.248.124 ganjincheng]# flock -hflock (util-linux-ng 2.17.2)Usage: flock [-sxun][-w #] fd# flock [-sxon][-w #] file [-c] command... flock [-sxon][-w #] directory [-c] command... -s --shared Get a shared lock -x --exclusive Get an exclusive lock -u --unlock Remove a lock -n --nonblock Fail rather than wait -w --timeout Wait for a limited amount of time -o --close Close file descriptor before running command -c --command Run a single command string through the shell -h --help Display this text -V --version Display version
Configuration example:
*/1 * * * * root flock -xn /tmp/mytest.lock -c 'php ./test.php'