并发下常见的加锁及锁的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设计模式之命令模式的深入解析
Jun 13 PHP
浅析PKI加密解密 OpenSSL
Jul 01 PHP
ThinkPHP CURD方法之table方法详解
Jun 18 PHP
Laravel 5 框架入门(四)完结篇
Apr 09 PHP
PHP文件缓存类实现代码
Oct 26 PHP
WordPress中登陆后关闭登陆页面及设置用户不可见栏目
Dec 31 PHP
PHP实现的自定义数组排序函数与排序类示例
Nov 18 PHP
php验证码生成器
May 24 PHP
laravel validate 设置为中文的例子(验证提示为中文)
Sep 29 PHP
浅谈laravel5.5 belongsToMany自身的正确用法
Oct 17 PHP
laravel邮件发送的实现代码示例
Jan 31 PHP
PHP超全局变量实现原理及代码解析
Sep 01 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
php download.php实现代码 跳转到下载文件(response.redirect)
2009/08/26 PHP
用Php编写注册后Email激活验证的实例代码
2013/03/11 PHP
PHP中使用CURL模拟登录并获取数据实例
2014/07/01 PHP
PHP使用fopen与file_get_contents读取文件实例分享
2016/03/04 PHP
javaScript年份下拉列表框内容为当前年份及前后50年
2014/05/28 Javascript
jQuery实现图片渐入渐出切换展示效果
2015/08/15 Javascript
js简单判断移动端系统的方法
2016/02/25 Javascript
Bootstrap Metronic完全响应式管理模板学习笔记
2016/07/08 Javascript
AngularJS  $modal弹出框实例代码
2016/08/24 Javascript
js 获取元素所有兄弟节点的实现方法
2016/09/06 Javascript
DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)
2016/11/09 Javascript
jQuery插件FusionCharts绘制的3D饼状图效果实例【附demo源码下载】
2017/03/03 Javascript
Angular中使用$watch监听object属性值的变化(详解)
2017/04/24 Javascript
vue-loader教程介绍
2017/06/14 Javascript
JavaScript事件方法(实例讲解)
2017/06/27 Javascript
jQuery基于cookie实现换肤功能实例
2017/10/14 jQuery
解决Vue 浏览器后退无法触发beforeRouteLeave的问题
2017/12/24 Javascript
ECharts地图绘制和钻取简易接口详解
2019/07/12 Javascript
微信小程序自定义单项选择器样式
2019/07/25 Javascript
使用Python来编写HTTP服务器的超级指南
2016/02/18 Python
Python中防止sql注入的方法详解
2017/02/25 Python
Python中的探索性数据分析(功能式)
2017/12/22 Python
selenium3+python3环境搭建教程图解
2018/12/07 Python
计算机二级python学习教程(1) 教大家如何学习python
2019/05/16 Python
使用Python在Windows下获取USB PID&amp;VID的方法
2019/07/02 Python
Python结合Window计划任务监测邮件的示例代码
2020/08/05 Python
详解css3使用transform出现字体模糊的解决办法
2020/10/16 HTML / CSS
意大利独特而优质的家居用品:Fazzini
2018/12/05 全球购物
自荐信怎么写好
2013/11/11 职场文书
致跳远、跳高运动员广播稿
2014/01/09 职场文书
自我鉴定四大框架
2014/01/17 职场文书
关于读书的演讲稿400字
2014/08/27 职场文书
电力企业职工培训心得体会
2016/01/11 职场文书
《半截蜡烛》教学反思
2016/02/19 职场文书
PHP新手指南
2021/04/01 PHP
linux目录管理方法介绍
2022/06/01 Servers