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

1 篇文章 0 订阅
1 篇文章 0 订阅

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

在最近的项目中有这样的场景

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 感谢孙同学的分享精神!

原文地址:http://www.cnblogs.com/scotoma/archive/2010/09/26/1836312.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值