首页 后端开发 php教程 php中原子操作与文件锁flock的介绍(代码示例)

php中原子操作与文件锁flock的介绍(代码示例)

Jan 28, 2019 am 10:00 AM
php

本篇文章给大家带来的内容是关于php中原子操作与文件锁flock的介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

php原子操作,文件锁flock,数据库事务

php没有继承posix标准支持的unix锁,只封装了一个linux系统调用flock(信号量也能做成锁),按理也是可以使用锁机制的,虽然效率低一点。
php脚本是运行在fastcgi容器中,而fastcgi是多进程的,所以如果php程序访问了临界资源,势必造成程序结果的不正确性。
估计还要考虑下fastcgi容器的问题

问题描述:黑客用的工具刷我们的后台
取消订单时会有退款,黑客并发取消订单,导致多次退款
如果请求一个一个来,哪怕间隔100毫秒,也是没有问题的

一个PHP处理过程是: 读退款标志,发现没退款, 退款,然后设置已退款标志
问题是多个请求同时到了,读出来的退款标志都是未退款,所以多个请求都退款了
同一个php文件,被同时请求多次,是同一时刻

用php文件锁flock 我们试了不行,还是用C++队列
用C++监听了一个端口,直接接收HTTP包,然后返回HTTP格式的包,PHP程序中用curl访问我这个C程序.
相当于远程调用了,可以部署到其他服务器做分布式了

很多时候,我们并没有考虑我们php代码的并行能力,尤其是在我们的php代码对某个资源可读可写的时候。但这并不是说php的所有操作就都是原子的,事务的,可并行的。由于php脚本是运行在fastcgi容器中,而fastcgi是多进程的,所以如果php程序访问了临界资源,势必造成程序结果的不正确性。

解决问题的办法是使用锁机制。php没有继承posix标准支持的unix锁:比如记录锁fcntl,线程锁等,而只封装了一个linux系统调用flock(信号量也能做成锁),flock形式为flock($fp,$type),其中$fp为文件句柄,而$type为:
/* 当一个文件的打开方式是可读可写的,通常需要向文件加入锁机制 */

1. LOCK_SH 共享锁:
通常为进程向文件请求读操作时需加共享锁。共享锁可支持任意个进程间的读操作,如果写一个加了共享锁的文件则进程阻塞进入SLEEP状态值到共享锁解锁

2. LOCK_EX 独占锁:
通常为进程向文件的写操作加独占锁,一旦文件加上了该锁,则其他任意进程访问该文件时都会阻塞,直到解锁为止。

3. LOCK_UN 解锁:
为加锁的文件句柄解锁

这样的加锁方式必然可以保证加锁程序块的原子性,但同时也牺牲了程序的效率,因此,我们实际的程序中应该在程序的加锁和解锁代码间嵌入尽量少的程序逻辑(尤其是独占锁),保证程序尽快解锁。

最后,附上加上锁机制以后的程序:

<?php 
$usrinfo = isset($_GET["usrinfo"])?$_GET["usrinfo"]:exit(1); 
$stinfo = isset($_GET["stinfo"])?$_GET["stinfo"]:exit(1); 
echo $stinfo; 
$pid = posix_getpid(); 
$fp = fopen(“usrinfo.txt”,”a+”); 
$num = rand(0,100000); 
flock($fp,LOCK_EX); 
fwrite($fp,”user:”.$usrinfo.” stinfo:”.$stinfo.”–”.$pid.”–”.$num.”\n”); 
fwrite($fp,”talking 1 — pid:$pid and num:$num\n”); 
flock($fp,LOCK_UN); 
fclose($fp);
登录后复制

普通情况运行该程序,产生正确的结果。

用什么方法可以在业务批量操作时保证原子性呢?
例如:删除多条文章,但在中间有一条已经被删除了,假设这里会出现错误,那如何让整个操作回滚,并定位错误信息呢?
数据库的事务保证原子性但不能定位错误信息,但遇到无法使用事务的场景,应该怎么做呢?

利用数据库的事务来做是最合理的,错误信息可以记录啊,有操作失败抛出错误。
应用逻辑来保证,就是每操作一次做下记录,成功失败都做下记录。中间出错,可以把成功的回滚。一般我们删除是假删除,所以很容易。如果真删除,记录时要记录完整信息。

PHP用文件锁模拟进程锁,实现原子操作
用PHP实现原子操作,而PHP本身并没有提供进程锁机制,用PHP文件锁机制,通过文件锁模拟进程锁实现原子操作。

原子操作的代码之前,使用排他锁打开某个文件,代码如下:

$fp = fopen( LOCK_FILE_PATH, "r" );
if (!$fp) {
 echo "Failed to open the lock file!"; 
 exit(1);//异常处理
 }
flock ( $fp, LOCK_EX );
登录后复制

原子操作的代码之后,对该文件解锁,并关闭文件,代码如下:

flock ( $fp, LOCK_UN );
fclose ( $fp );
登录后复制

整体伪代码为:

define("LOCK_FILE_PATH", "/tmp/lock");
if( !file_exists(LOCK_FILE_PATH) ){ 
$fp = fopen( LOCK_FILE_PATH, "w" );
fclose ( $fp );
}
$fp = fopen( LOCK_FILE_PATH, "r" );
if (!$fp) {
echo "Failed to open the lock file!";
exit(1);//异常处理
}
flock ( $fp, LOCK_EX );
//此处添加原子操作代码
flock ( $fp, LOCK_UN );
fclose ( $fp );
登录后复制

以上便可实现PHP原子操作,避免冲突。

php原子操作与mysql原子操作

原子操作常用的方法就是通过数据回滚来实现,用 PHP 来实现数据库回滚操作相当简单:
1, 建立数据库连接
2, mysql_query('BEGIN'); 开启事务
3, $SQL = "..."; 
mysql_query($SQL); 做相应的数据库操作
4, 判断回滚条件:
if(mysql_errno) 

print mysql_error(); 
mysql_query('ROLLBACK'); 出错就回滚 
exit(); 

5,可以重复上述步骤 3 及步骤 4 的操作, 开始的过程(中间可以加入其他操作,不局限于数据库更新,但是注意,最好不要让一个事务时间过长,因为它锁定所有你用到的表,会影响其他程序使用) 
你也可以在几条正确的sql更新语句后故意写一句错误的,看看是否回滚了。
6, 结束回滚操作
mysql_query('COMMIT'); 能够到这里,代表上述数据库操作都没有错,正式提交执行

这就是用 PHP 实现原子操作的整个过程,需要特别注意的是建立支持数据回滚操作的表结构,
另外,除 commit 外也有其它办法可以结束回滚操作。


以上是php中原子操作与文件锁flock的介绍(代码示例)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

CakePHP 项目配置 CakePHP 项目配置 Sep 10, 2024 pm 05:25 PM

在本章中,我们将了解CakePHP中的环境变量、常规配置、数据库配置和电子邮件配置。

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

CakePHP 日期和时间 CakePHP 日期和时间 Sep 10, 2024 pm 05:27 PM

为了在 cakephp4 中处理日期和时间,我们将使用可用的 FrozenTime 类。

CakePHP 文件上传 CakePHP 文件上传 Sep 10, 2024 pm 05:27 PM

为了进行文件上传,我们将使用表单助手。这是文件上传的示例。

CakePHP 路由 CakePHP 路由 Sep 10, 2024 pm 05:25 PM

在本章中,我们将学习以下与路由相关的主题?

讨论 CakePHP 讨论 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的开源框架。它的目的是使应用程序的开发、部署和维护变得更加容易。 CakePHP 基于类似 MVC 的架构,功能强大且易于掌握。模型、视图和控制器 gu

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

CakePHP 创建验证器 CakePHP 创建验证器 Sep 10, 2024 pm 05:26 PM

可以通过在控制器中添加以下两行来创建验证器。

See all articles