「真实案例」php文件锁产生的问题和解决方案
xsobi 2024-12-29 06:47 1 浏览
本文为php中文网认证作者:“齐天大圣”投稿,欢迎加入php中文网有偿投稿计划!
一个真实案例
想起自己之前犯过一个相关的错误。当时场景是这样的:有一个微信公众号项目,调用微信公众号的接口都需要access_token,它的有效期是2小时。当时我的做法是把它存放在文件中,格式使用的是json。{"access_token":"easWasdw32323", "expire":1588219064}。伪代码如下:
function getToken ($tokenFile)
{
$tokenJson = file_get_contents($tokenFile);
if (!$tokenJson) {
$token = loadToken($tokenFile);
} else if (json_decode($tokenJson, true)['expire'] <= time()){
$token = loadToken($tokenFile);
} else {
$token = json_decode($tokenJson, true)['access_token'];
}
return $token;
}
function loadToken ($tokenFile)
{
$fp = fopen($tokenFile, 'r+');
$tokenJson = ...; // 调用微信接口获取到token
fwrite($fp, json_encode($tokenJson));
return $tokenJson['access_token'];
}
出现的问题:
项目运行一段时间后就会出问题,但过一两秒后再刷新就正常了。
问题原因分析:
假设token已经过期了,这时候有2个请求来了,分别命名为A、B。A来了,发现token到期后,去调用微信接口获取新的token,获取后,更新到存放token的文件中。
但是,文件没有完全更新完毕的时候,B来了,读入存放token的文件。因为token文件中数据没有更新完整,B读到的数据就会产生错误。
另外还有可能是A和B同时在更新文件内容,这样就会产生数据混乱,也会导致错误发生。
如何规避这个错误呢?
文件锁机制可以完成。
在PHP中提供了 flock()函数,可以对文件使用锁定机制(锁定或释放文件)。当一个进程在访问文件时加上锁,其他进程要想对该文件进行访问,则必须等到锁定被释放以后。这样就可以避免在并发访问同一个文件时破坏数据。
函数原型如下:
flock ( resource $handle , int $operation [, int &$wouldblock ] ) : bool
- handle:文件系统指针,是典型地由 fopen() 创建的 resource(资源)。
- operation
operation 可以是以下值之一:
LOCK_SH取得共享锁定(读取的程序)。
LOCK_EX 取得独占锁定(写入的程序)。
LOCK_UN 释放锁定(无论共享或独占)。
LOCK_NB附加锁定(Windows 上还不支持)。
- wouldblock
如果锁定会堵塞的话(EWOULDBLOCK 错误码情况下),可选的第三个参数会被设置为 TRUE。(Windows 上不支持)
demo
demo1.php
<?php
$file = 'data.txt';
$handler = fopen($file, 'a+') or die('文件资源打开失败');
// 取得独占锁
if (flock($handler, LOCK_EX)) {
sleep(5);
flock($handler, LOCK_UN);
} else {
echo '锁定失败';
}
fclose($handler);
demo2.php
<?php
$file = 'data.txt';
$handler = fopen($file, 'a+') or die('文件资源打开失败');
// 取得独占锁
if (flock($handler, LOCK_EX)) {
fwrite($handler, 'sometest string');
flock($handler, LOCK_UN);
} else {
echo '锁定失败';
}
fclose($handler);
先运行demo1.php然后立即运行demo2.php,会发现,因为被demo1.php锁定了文件,demo2.php写入不了新内容,只有等demo1.php释放了锁定,demo2.php才能拿到独占锁,然后才能写入文件。
解决问题
学完这些知识后,就能解决我之前的问题了。改进的代码如下:
<?php
function getToken ($tokenFile){
$tokenJson = file_get_contents($tokenFile);
if (!$tokenJson) {
$token = loadToken($tokenFile);
} else if (json_decode($tokenJson, true)['expire'] <= time()){
$token = loadToken($tokenFile);
} else {
$token = json_decode($tokenJson, true)['access_token'];
}
return $token;
}
function loadToken ($tokenFile) {
$fp = fopen($tokenFile, 'w'); // 取得独占锁
if (flock($fp, LOCK_EX)) {
$tokenJson = ...; // 调用微信接口获取到token
fwrite($fp, json_encode($tokenJson));
flock($fp, LOCK_UN);
} else {
return false;
}
return $tokenJson['access_token'];
}
- 上一篇:PHP大文件读取操作 php大文件处理
- 已经是最后一篇了
相关推荐
- 「真实案例」php文件锁产生的问题和解决方案
-
本文为php中文网认证作者:“齐天大圣”投稿,欢迎加入php中文网有偿投稿计划!一个真实案例想起自己之前犯过一个相关的错误。当时场景是这样的:有一个微信公众号项目,调用微信公众号的接口都需要acces...
- PHP大文件读取操作 php大文件处理
-
简单的文件读取,一般我们会使用file_get_contents()这类方式来直接获取文件的内容。不过这种函数有个严重的问题是它会把文件一次性地加载到内存中,也就是说,它会受到内存的限制。因此,加...
- Linux文件链接(软硬)的介绍及其应用
-
linux中对文件的链接分为两种,一种是硬链接,另一种是软链接。今天和大家介绍下这两种链接,以及如何去使用他们。硬链接首先我们来看硬链接,我们来用php中变量的引用来对比吧。$a=100;$b...
- 包含connect.php文件的写法以及循环输出查询结果
-
包含connect.php文件的写法以及循环输出查询结果我们先把代码写在下面:<?phprequire_once("./connect.php");$sql="selec...
- PHP读取文件内容的五种方式 php读取txt
-
读取文件内容的五种方式分享下php读取文件内容的五种方法:好吧,写完后发现文件全部没有关闭。实际应用当中,请注意关闭fclose($fp);--...
- 多学习才能多赚钱之:php文件怎样打开和运行
-
php-fpm的进程数可以根据设置分为动态和静态。静态:直接开启指定数量的php-fpm进程,不再增加或者减少;动态:开始的时候开启一定数量php-fpm进程,当请求变大的时候,动态的增加php-fp...
- PHP函数和文件 php中的文件包含语句以及各自的异同点
-
程序员编程语言之间的鄙视链:...
- Linux服务器出现Socket Error「Too many open files」怎么办
-
最近在用freeswitch软交换进行语音通话,通话的时候需要调用音频文件进行播放,当并发量上来的时候,freeswitch监听服务的端口会不断的down掉,查看日志发现报了一个错如下:这个问题经常...
- CMS系统天花板!这可能是在开源界上最值得推荐的CMS系统了
-
系统简介novel-plus是一款功能完善的原创文学CMS系统,支持多端使用(PC、WAP)阅读。由前台门户系统、作家后台管理系统、平台后台管理系统和爬虫管理系统等多个子系统构成...
- 用织梦建站的公司企业你们瑟瑟发抖吗?织梦开启维权之路索赔不低
-
织梦也就是dedecms这个网站内容管理系统,织梦建网站曾经在很长一段时间内非常出名,几乎成为建站首选,个人自不必说,很多小建站公司也是用的织梦直接来套站,虽然吧强梦系统漏洞bug一大堆,但是因为简便...
- 六个优质开源项目,让你更了解Django框架开发
-
Django是一个开源的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。它最初是被用来开发CMS软件的,所以Django很适合用来搭...
- Python的Web开发--第一个Django项目
-
Python有强大的数据库,那么对数据分析之后的结果需要在web上展现,当然我们也可以借助Java等框架,但是多此一举,虽然python生态圈没有Java完善,但python有自己的轻量级和重量级框...
- 基于AHNCMs-15的对称超级电容器,纳米碳模板和预陶瓷聚合物如何
-
在阅读此文前,诚邀您请点点右上方的“关注”,既方便您进行讨论与分享,还能及时阅读最新内容,感谢您的支持。基于AHNCMs-15的对称超级电容器具有14.7Whkg的高能量密度?1在250瓦克的功率...
- 「某CMS漏洞」SQL注入漏洞分析 sql注入漏洞原理、常见测试方法及防御方法
-
前言这个CMS非常适合入门代码审计的人去学习,因为代码简单且漏洞成因经典,对一些新手有学习价值,...
- 织梦cms怎么添加商桥? 织梦cms教程
-
作为一个前端的销售人员,很多人会自己去买服务器域名做网站,当我们网站做好以后希望安装一个商桥上去,这样就可以在线沟通交互了。相信也有很多和我一样看不懂代码的小伙伴在问怎么添加商桥代码到网站文件中,我...
- 一周热门
- 最近发表
- 标签列表
-
- grid 设置 (58)
- 移位运算 (48)
- not specified (45)
- patch补丁 (31)
- 导航栏 (58)
- context xml (46)
- scroll (43)
- element style (30)
- dedecms模版 (53)
- vs打不开 (29)
- nmap (30)
- c 视频教程下载 (33)
- listview排序 (33)
- firebug 使用 (31)
- transactionmanager (30)
- characterencodingfilter (33)
- getmonth (34)
- commandtimeout (30)
- hibernate教程 (31)
- label换行 (33)
- curlpost (31)
- android studio 3 0 (34)
- android开发视频 (30)
- android应用开发 (31)
- html转js (35)