PHP并发操作时的加锁功能

只容许一个用户在一个时间内进行操作
服务器君一共花费了158.299 ms进行了4次数据库查询,努力地为您提供了这个页面。
试试阅读模式?希望听取您的建议

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

针对以上的2种情况,现在的解决方法是对处理过程进行锁机制,通过PHP实现如下:

用到了Eaccelerator的内存锁和文件锁,原理:判断系统中是否安了EAccelerator如果有则使用内存锁,如果不存在,则进行文件锁。根据带入的key的不同可以实现多个锁直接的并行处理,类似Innodb的行级锁。

具体类如下:

<?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);
		}
	}
}
?>

使用如下:

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

本文地址:http://www.nowamagic.net/librarys/veda/detail/335,欢迎访问原出处。

不打个分吗?

转载随意,但请带上本文地址:

http://www.nowamagic.net/librarys/veda/detail/335

如果你认为这篇文章值得更多人阅读,欢迎使用下面的分享功能。
小提示:您可以按快捷键 Ctrl + D,或点此 加入收藏

阅读一百本计算机著作吧,少年

很多人觉得自己技术进步很慢,学习效率低,我觉得一个重要原因是看的书少了。多少是多呢?起码得看3、4、5、6米吧。给个具体的数量,那就100本书吧。很多人知识结构不好而且不系统,因为在特定领域有一个足够量的知识量+足够良好的知识结构,系统化以后就足以应对大量未曾遇到过的问题。

奉劝自学者:构建特定领域的知识结构体系的路径中再也没有比学习该专业的专业课程更好的了。如果我的知识结构体系足以囊括面试官的大部分甚至吞并他的知识结构体系的话,读到他言语中的一个词我们就已经知道他要表达什么,我们可以让他坐“上位”毕竟他是面试官,但是在知识结构体系以及心理上我们就居高临下。

所以,阅读一百本计算机著作吧,少年!

《程序员修炼之道:从小工到专家》 亨特(Andrew Hunt) (作者), 托马斯(David Thomas) (作者), 马维达 (译者)

《程序员修炼之道:从小工到专家》内容简介:《程序员修炼之道》由一系列独立的部分组成,涵盖的主题从个人责任、职业发展,知道用于使代码保持灵活、并且易于改编和复用的各种架构技术,利用许多富有娱乐性的奇闻轶事、有思想性的例子及有趣的类比,全面阐释了软件开发的许多不同方面的最佳实践和重大陷阱。无论你是初学者,是有经验的程序员,还是软件项目经理,《程序员修炼之道:从小工到专家》都适合你阅读。

更多计算机宝库...