Home  >  Article  >  Backend Development  >  Example analysis of PHP file lock and process lock

Example analysis of PHP file lock and process lock

小云云
小云云Original
2018-01-30 10:41:281654browse

In view of the introduction of swoole before, we will use swoole's server/client and multi-process mechanism to explain the lock. This article mainly introduces the use examples of PHP file lock and process lock. Here we only explain the lock mechanism of PHP. Since SQL locks are different in their mode of action and application scenarios, and will be explained separately. I hope it can help everyone.

1. File lock

  • ##flock()

  • ##fclose()
  • swoole_lock()
  • Possible application scenarios of file lock are:

1. Limit concurrent multiple processes or multiple servers that need to access and modify the same file;


2. Queuing and artificial blocking of processes participating in file I/O;


3.Guarding file contents in business logic;


The following is the use of file lock C/S communication mechanism, the specific communication process has been omitted

Server (the server communication process has been omitted):

//监听数据发送事件
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
  $serv->send($fd, "ServerEnd");

  $p_file = "locktest.txt";
  var_dump(file_get_contents($p_file));
});

Client1 (Server The communication process has been omitted):

$s_recv = "ww";

$p_file = "locktest.txt";

$o_file = fopen($p_file,'w+');
// flock()加锁方式:
flock($o_file,LOCK_EX);

// // swoole加锁方式:
// $lock = new swoole_lock(SWOOLE_FILELOCK, $p_file);
// $lock->lock();

fwrite($o_file, 'ss' . $s_recv);

sleep(30);
// 两种解锁方式
// flock($o_file, LOCK_UN);
// $lock->unlock();

Client2 (The server communication process has been omitted):

$s_recv = "xx";

$p_file = "locktest.txt";

$o_file = fopen($p_file,'w+');
// flock()加锁方式:
flock($o_file,LOCK_EX);

// // swoole加锁方式:
// $lock = new swoole_lock(SWOOLE_FILELOCK, $p_file);
// $lock->lock();


fwrite($o_file, 'ss' . $s_recv);

// 两种解锁方式
// flock($o_file, LOCK_UN);
// $lock->unlock();

Result:


Client2 was blocked for 30s until the execution of Client1 ended The file has just been written once;

[l0.16@4 m29.5% c30s04] $ php swoole_client2.php

It should be noted that:

1. Whether it is flock() or swoole_lock() provided by swoole, it will automatically unlock when the process ends. mechanism, so it can run normally even without manual unlocking in the demo, so the sleep() pause function is executed in the first Client to observe the effect of the file lock;


2. The standard release method of flock() is flock($file,LOCK_UN);, but I personally like fclose() to avoid future troubles;


2. Process lock

and file lock The difference is that process locks are not used to prevent I/O to files, but to prevent unexpected consequences caused by the concurrency of multiple processes. Therefore, it is necessary to queue them when multiple processes are concurrent, that is, in a process Block the logic execution of other concurrent processes before the execution of key logic ends.

There are several implementation ideas:

1. Use flock() file lock to create a temporary lock file and use LOCK_NB to simulate blocking Or non-blocking flow, and then use judgment conditions to control logic execution inside the process;

Non-blocking model demo:

$p_file = "locktest.txt";
$o_file = fopen($p_file, 'w+');

// 如果临时文件被锁定,这里的flock()将返回false
if (!flock($o_file, LOCK_EX + LOCK_NB)) {
  var_dump('Process Locked');
}
else {
  // 非阻塞模型必须在flock()中增加LOCK_NB参数
  // 当然,这里取消LOCK_NB参数就是阻塞模型了
  flock($o_file, LOCK_EX + LOCK_NB);
  var_dump('Process Locking');
  // 模拟长时间的执行操作
  sleep(10);
}

2. Use the shared memory, caching method or communication method provided by swoole in different Pass a global variable in the process, and the process uses the judgment condition to control the logic execution after obtaining the status of the variable;

There are many ways to pass variables, here is only one idea, taking memcached as an example;


Blocking model demo:

// 初始化memcached
$memcached = new Memcache;
$memcached->connect("localhost", 11211);

// 获取用来做状态判定的全局变量
$s_flag = $memcached->get("flag");

if (!$s_flag) {
  // 这里利用了memcached的过期时间作为演示,实际上业务处理完成后销毁该变量即可
  $memcached->set("flag", "locked", 0, 10);
  main();
}
else {
  // 阻塞模型
  while ($s_flag == 'locked') {
    var_dump('Process locked, retrying...');
    // 设置重试时间, 避免过于频繁的操作尝试
    sleep(1);
    // 更新状态变量
    $s_flag = $memcached->get("flag");
  }
  // // 非阻塞模型
  // if ($s_flag == 'locked') {
  //   var_dump('Process locked, suspended');
  //   die();
  // }
  main();
}

// 模拟业务主函数
function main() {
  var_dump('Process Running');
  // 业务执行结束后回收memcached
  // $memcached->delete("flag");
}

What needs to be noted here is:


1. The expiration time of memcached cannot be less than the actual time of program running, so it is recommended to be slightly longer One point, recycle after the logic execution is completed;


2. In the non-blocking model, if the status is judged to be false, the process should be terminated or blocked to avoid the continued execution of the business logic;


3. In practical applications, it is necessary to set a retry time, which can greatly reduce the large amount of I/O concurrency for memcached and reduce server pressure;


Related recommendations:


Detailed explanation of file locks, mutex locks, and read-write locks in PHP

A brief introduction to PHP file locks and process locks

Compare the differences between the use of file locks and process locks in PHP

The above is the detailed content of Example analysis of PHP file lock and process lock. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn