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

2015-01-24信息快讯网
在最近的项目中有这样的场景
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 感谢孙同学的分享精神!
windows环境下php配置memcache的具体操作步骤
基于wordpress主题制作的具体实现步骤
基于ubuntu下nginx+php+mysql安装配置的具体操作步骤
php获取本地图片文件并生成xml文件输出具体思路
php中用于检测一个地理IP地址是否可用的代码
PHP类的静态(static)方法和静态(static)变量使用介绍
php 删除一个数组中的某个值.兼容多维数组!
php 获取百度的热词数据的代码
php 网上商城促销设计实例代码
php中通过curl模拟登陆discuz论坛的实现代码
php线性表顺序存储实现代码(增删查改)
用PHP实现Ftp用户的在线管理
php后台多用户权限组思路与实现程序代码分享
php+iframe实现隐藏无刷新上传文件
PHP如何解决网站大流量与高并发的问题
PHP OPCode缓存 APC详细介绍
PHP开发的一些注意点总结
php更改目录及子目录下所有的文件后缀的代码
比较全面的PHP数组的使用方法小结
PHP之COOKIE支持详解
PHPCMS的使用小结
用PHP将数据导入到Foxmail的实现代码
PHP安全技术之 实现php基本安全
利用Memcached在php下实现session机制 替换PHP的原生session支持
php 过滤器实现代码
php递归实现无限分类生成下拉列表的函数
通过具体程序来理解PHP里面的抽象类
PHP下通过系统信号量加锁方式获取递增序列ID
定制404错误页面,并发信给管理员的程序
多php服务器实现多session并发运行
在apache下限制每个虚拟主机的并发数!!!!
©2014-2024 dbsqp.com