并发下常见的加锁及锁的PHP具体实现代码


Posted in PHP onOctober 12, 2010

在最近的项目中有这样的场景
1.生成文件的时候,由于多用户都有权限进行生成,防止并发下,导致生成的结果出现错误,需要对生成的过程进行加锁,只容许一个用户在一个时间内进行操作,这个时候就需要用到锁了,将这个操作过程锁起来.
2.在用了cache的时候,cache失效可能导致瞬间的多数并发请求穿透到数据库此时也可以得需要用锁在同一并发的过程中将这个操作锁定.

针对以上的2种情况,现在的解决方法是对处理过程进行锁机制,通过PHP实现如下
用到了Eaccelerator的内存锁 和 文件锁,原理如下
判断系统中是否安了EAccelerator 如果有则使用内存锁,如果不存在,则进行文件锁
根据带入的key的不同可以实现多个锁直接的并行处理,类似Innodb的行级锁

使用如下:
$lock = new CacheLock('key_name');
$lock->lock();
//logic here
$lock->unlock();
//使用过程中需要注意下文件锁所在路径需要有写权限.
具体类如下:

<?php 
/** 
* CacheLock 进程锁,主要用来进行cache失效时的单进程cache获取,防止过多的SQL请求穿透到数据库 
* 用于解决PHP在并发时候的锁控制,通过文件/eaccelerator进行进程间锁定 
* 如果没有使用eaccelerator则进行进行文件锁处理,会做对应目录下产生对应粒度的锁 
* 使用了eaccelerator则在内存中处理,性能相对较高 
* 不同的锁之间并行执行,类似mysql innodb的行级锁 
* 本类在sunli的phplock的基础上做了少许修改 http://code.google.com/p/phplock 
* @author yangxinqi 
* 
*/ 
class CacheLock 
{ 
//文件锁存放路径 
private $path = null; 
//文件句柄 
private $fp = null; 
//锁粒度,设置越大粒度越小 
private $hashNum = 100; 
//cache key 
private $name; 
//是否存在eaccelerator标志 
private $eAccelerator = false; 
/** 
* 构造函数 
* 传入锁的存放路径,及cache key的名称,这样可以进行并发 
* @param string $path 锁的存放目录,以"/"结尾 
* @param string $name cache key 
*/ 
public function __construct($name,$path='lock\\') 
{ 
//判断是否存在eAccelerator,这里启用了eAccelerator之后可以进行内存锁提高效率 
$this->eAccelerator = function_exists("eaccelerator_lock"); 
if(!$this->eAccelerator) 
{ 
$this->path = $path.($this->_mycrc32($name) % $this->hashNum).'.txt'; 
} 
$this->name = $name; 
} 
/** 
* crc32 
* crc32封装 
* @param int $string 
* @return int 
*/ 
private function _mycrc32($string) 
{ 
$crc = abs (crc32($string)); 
if ($crc & 0x80000000) { 
$crc ^= 0xffffffff; 
$crc += 1; 
} 
return $crc; 
} 
/** 
* 加锁 
* Enter description here ... 
*/ 
public function lock() 
{ 
//如果无法开启ea内存锁,则开启文件锁 
if(!$this->eAccelerator) 
{ 
//配置目录权限可写 
$this->fp = fopen($this->path, 'w+'); 
if($this->fp === false) 
{ 
return false; 
} 
return flock($this->fp, LOCK_EX); 
}else{ 
return eaccelerator_lock($this->name); 
} 
} 
/** 
* 解锁 
* Enter description here ... 
*/ 
public function unlock() 
{ 
if(!$this->eAccelerator) 
{ 
if($this->fp !== false) 
{ 
flock($this->fp, LOCK_UN); 
clearstatcache(); 
} 
//进行关闭 
fclose($this->fp); 
}else{ 
return eaccelerator_unlock($this->name); 
} 
} 
}

本类在孙立同学的类的基础上做了小点改进的了.具体可以看 http://code.google.com/p/phplock 感谢孙同学的分享精神!
PHP 相关文章推荐
PHP的分页功能
Mar 21 PHP
PHP生成网页快照 不用COM不用扩展.
Feb 11 PHP
php echo 输出字符串函数详解
May 13 PHP
php中实现记住密码自动登录的代码
Mar 02 PHP
PHP $_FILES函数详解
Mar 09 PHP
深入解读php中关于抽象(abstract)类和抽象方法的问题分析
Jan 03 PHP
php mail to 配置详解
Jan 16 PHP
php实现excel中rank函数功能的方法
Jan 20 PHP
php 函数使用可变数量的参数方法
May 02 PHP
Laravel框架模板加载,分配变量及简单路由功能示例
Jun 11 PHP
在Ubuntu 18.04上安装PHP 7.3 7.2和7.0的方法
Apr 09 PHP
Yii框架安装简明教程
May 15 PHP
PHP开发的一些注意点总结
Oct 12 #PHP
php更改目录及子目录下所有的文件后缀的代码
Sep 24 #PHP
比较全面的PHP数组的使用方法小结
Sep 23 #PHP
PHP之COOKIE支持详解
Sep 20 #PHP
PHPCMS的使用小结
Sep 20 #PHP
PHP中的MYSQL常用函数(php下操作数据库必备)
Sep 12 #PHP
zen cart新进商品的随机排序修改方法
Sep 10 #PHP
You might like
星际流派综述
2020/03/04 星际争霸
php5 and xml示例
2006/11/22 PHP
PHP编码规范的深入探讨
2013/06/06 PHP
php上传文件常见问题总结
2015/02/03 PHP
详解Laravel5.6 Passport实现Api接口认证
2018/07/27 PHP
JavaScript面向对象之体会[总结]
2008/11/13 Javascript
JS 学习笔记 防止发生命名冲突
2009/07/30 Javascript
100个不能错过的实用JS自定义函数
2014/03/05 Javascript
javascript实现2048游戏示例
2014/05/04 Javascript
JS往数组中添加项性能分析
2015/02/25 Javascript
JavaScript对象数组排序实例方法浅析
2016/06/15 Javascript
基于JavaScript实现在新的tab页打开url
2016/08/04 Javascript
ionic进入多级目录后隐藏底部导航栏(tabs)的完美解决方案
2016/11/23 Javascript
基于vue的下拉刷新指令和滚动刷新指令
2016/12/23 Javascript
详解Vue.js入门环境搭建
2017/03/17 Javascript
vue 计时器组件的实现代码
2017/09/14 Javascript
electron-vue开发环境内存泄漏问题汇总
2019/10/10 Javascript
关于在LayUI中使用AJAX提交巨坑记录
2019/10/25 Javascript
如何在wxml中直接写js代码(wxs)
2019/11/14 Javascript
vue实现导航菜单和编辑文本的示例代码
2020/07/04 Javascript
[06:06]2018DOTA2亚洲邀请赛主赛事第四日战况回顾 全明星赛欢乐上演
2018/04/07 DOTA
python映射列表实例分析
2015/01/26 Python
Python字符和字符值(ASCII或Unicode码值)转换方法
2015/05/21 Python
python避免死锁方法实例分析
2015/06/04 Python
python利用Tesseract识别验证码的方法示例
2019/01/21 Python
使用python 计算百分位数实现数据分箱代码
2020/03/03 Python
如何理解python对象
2020/06/21 Python
css3遮罩层镂空效果的多种实现方法
2020/05/11 HTML / CSS
俄罗斯在线购买飞机票、火车票、巴士票网站:Tutu.ru
2020/03/16 全球购物
比较基础的php面试题及答案-编程题
2012/10/14 面试题
2014年乡镇植树节活动方案
2014/02/28 职场文书
电焊工岗位工作职责
2014/07/09 职场文书
四查四看整改措施
2014/09/19 职场文书
王兆力在市委党的群众路线教育实践活动总结大会上的讲话稿
2014/10/25 职场文书
会计手工模拟做账心得体会
2016/01/22 职场文书
python3实现Dijkstra算法最短路径的实现
2021/05/12 Python