在最近的项目中有这样的场景 
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);
}
}
}

  

最新文章

  1. 三星S4,呼转的来电,在来电界面上不显示的解决方案
  2. php中的ip2long和long2ip的理解
  3. python windows终端窗口下输出编码错误
  4. Exchange 2010 邮箱大小限制原则
  5. poj 3177 边连通分量
  6. Cocos2dx边学边总结——开篇(一)
  7. 持续集成Jenkins+sonarqube部署教程
  8. easyUI resizable组件使用
  9. linux下mysql修改root密码
  10. 不借助第三方网站四步实现手机网站转安卓APP
  11. 冲刺NO.12
  12. UDK命令
  13. 页面启动jquery
  14. java中JDBC连接Oracle数据库
  15. linux 根据进程名杀死进程 -kill进程名
  16. December 18th 2016 Week 52nd Sunday
  17. ansible modules开发(一)
  18. npm 淘宝镜像安装以及安装报错window_nt 6.1.7601 解决
  19. 解决Linux环境下安装xampp之后外部无法连接MySQL的问题
  20. 在Ubuntu安装Tomcat7.0及开机自动运行

热门文章

  1. 【POJ 2528】Mayor’s posters(线段树+离散化)
  2. Thinking in java学习笔记之finalize
  3. Java多线程与并发库高级应用-java5线程并发库
  4. JVM学习笔记:字节码执行引擎
  5. java web项目导入到eclipse中变成了java项目的一种情况的解决办法
  6. Webpack打包工具实时更新操作(启用观察者模式)
  7. Windows Directory ACL Security Check By ACL Baseline
  8. Android虚拟机Classic qemu does not support SMP问题记录
  9. 手机卫士开发记录之handler错误
  10. Centos提示-bash: make: command not found的解决办法