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

转载 2015年07月06日 20:35:07

<span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; background-color: rgb(245, 245, 245);">在最近的项目中有这样的场景</span>

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具体实现
  • u011986449
  • u011986449
  • 2016年05月26日 17:45
  • 3265

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

并发下常见的加锁及锁的PHP具体实现 在最近的项目中有这样的场景 1.生成文件的时候,由于多用户都有权限进行生成,防止并发下,导致生成的结果出现错误,需要对生成的过程进行加锁,只容许一个用...
  • dy357978912
  • dy357978912
  • 2015年09月22日 16:10
  • 1320

利用ZooKeeper简单实现分布式锁

下面讲解下怎么利用ZooKeeper简单实现分布式锁,对于zk的安装和简单使用请参考我的文章:Hadoop集群之 ZooKeeper和Hbase环境搭建...
  • peace1213
  • peace1213
  • 2016年09月18日 09:00
  • 6224

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

在最近的项目中有这样的场景 1.生成文件的时候,由于多用户都有权限进行生成,防止并发下,导致生成的结果出现错误,需要对生成的过程进行加锁,只容许一个用户在一个时间内进行操作,这个时候就需要用到锁...
  • kaosini
  • kaosini
  • 2013年05月20日 10:28
  • 658

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

在最近的项目中有这样的场景 1.生成文件的时候,由于多用户都有权限进行生成,防止并发下,导致生成的结果出现错误,需要对生成的过程进行加锁,只容许一个用户在一个时间内进行操作,这个时候就需要用到锁了,...
  • insisted_search
  • insisted_search
  • 2016年04月26日 08:37
  • 131

Java Socket第一个通讯程序的具体实现及常见问题的分析

搭建服务器类         服务器的搭建具体分为三个步骤:                 a:创建一个服务器套接字,并指定端口号。如: Server...
  • csu_passer
  • csu_passer
  • 2017年01月13日 13:05
  • 554239

PHP使用之上传图片到指定位置路径保存到数据库的具体实现

本文为大家介绍下php上传图片到指定位置路径保存到数据库的具体实现,感兴趣的朋友不要错过 1.conn.php ...
  • yxys01
  • yxys01
  • 2015年04月07日 20:19
  • 559

php 阿里大鱼手机验证码 ajax具体实现

1.阿里大鱼开启功能 (1)利用淘宝登录阿里大鱼, 免去身份验证。 (2)打开阿里大鱼管理中心 (3)添加一个短信模板 (4)添加短信签名,这个在以后都是会用到的 (5)创建一个应用 (6) 下载sd...
  • just_for_your_smile
  • just_for_your_smile
  • 2016年11月03日 16:33
  • 2555

PHP语言开发Paypal支付demo的具体实现

一、开发前准备 https://developer.paypal.com/  到paypal的开发者官网注册开发者账号。用账号登录之后、点击导航上面的 dashboard、进入dashboard...
  • zhaanghao
  • zhaanghao
  • 2015年12月13日 21:31
  • 224

PHP语言开发Paypal支付demo的具体实现

一、开发前准备 https://developer.paypal.com/  到paypal的开发者官网注册开发者账号。用账号登录之后、点击导航上面的 dashboard、进入dashboard...
  • hwk_yellow
  • hwk_yellow
  • 2016年11月16日 10:26
  • 260
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[转]并发下常见的加锁及锁的PHP具体实现
举报原因:
原因补充:

(最多只允许输入30个字)