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

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

http://www.cnblogs.com/scotoma/archive/2010/09/26/1836312.html

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

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

Apache + PHP 的并发访问

文章地址:http://www.cnblogs.com/WestContinent/archive/2013/03/25/2981667.html
1.书写例程:

做成一个测试用的PHP文件代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

<?php

//为了测试是否多个用户访问的时候这个值是公用的,即:是否临界资源

$count = 0;

//循环十次,消耗十秒,模拟一个费时操作

for ($i=1; $i<=10; $i++,$count++) {

  

    echo getTime()." i is $i and count is $count.</br>";

    sleep(1);

}

/**

 * 获得当前时间,返回字符串,包含毫秒数

 * 格式:yyyy-MM-dd HH:mm:ss.fff

 */

function getTime()

{

    $currentTime Date(‘Y-m-d H:i:s‘);//Get currentTime str

    $milisecond = microtime();

    $splitmiliTime explode(‘.‘$milisecond);

    $milisecond $splitmiliTime[1];

    $milisecond substr($milisecond, 0,3);

    $currentTime $currentTime.‘.‘.$milisecond;

    return $currentTime;

}

?>

2.把上面做成的文件Copy到Apache的发布目录(一般是Htdocs,但是可以配置)

3.打开两个浏览器同时访问发布PHP页面

分别得到如下结果

浏览器1

2013-03-25 14:55:42.128 i is 1 and count is 0.

2013-03-25 14:55:43.138 i is 2 and count is 1.

2013-03-25 14:55:44.152 i is 3 and count is 2.

2013-03-25 14:55:45.169 i is 4 and count is 3.

2013-03-25 14:55:46.180 i is 5 and count is 4.

2013-03-25 14:55:47.194 i is 6 and count is 5.

2013-03-25 14:55:48.208 i is 7 and count is 6.

2013-03-25 14:55:49.222 i is 8 and count is 7.

2013-03-25 14:55:50.236 i is 9 and count is 8.

2013-03-25 14:55:51.250 i is 10 and count is 9.

浏览器2

2013-03-25 14:55:41.286 i is 1 and count is 0.

2013-03-25 14:55:42.296 i is 2 and count is 1.

2013-03-25 14:55:43.310 i is 3 and count is 2.

2013-03-25 14:55:44.324 i is 4 and count is 3.

2013-03-25 14:55:45.339 i is 5 and count is 4.

2013-03-25 14:55:46.355 i is 6 and count is 5.

2013-03-25 14:55:47.367 i is 7 and count is 6.

2013-03-25 14:55:48.402 i is 8 and count is 7.

2013-03-25 14:55:49.645 i is 9 and count is 8.

2013-03-25 14:55:50.658 i is 10 and count is 9.

4.结论

从上面的试验结果可以得到如下结论,因为两组测试数据中的时间犬牙交错,两个用户在耗时操作中并没有出现某一个用户长时间占用执行时间片的情况。说明Apache+Php(loadmodule)是支持多用户并行操作的。另外全局变量Count在两个用户同时访问的时候都是以全新的状态出现的,因此Apache+Php(loadmodule)不支持内存缓存数据,也就是说在多用户并发访问的情况下每次访问都会开辟新的内存。那么如果需要对多用户的操作做同步,只能使用文件锁的方式来实现了。

加锁解锁PHP实现

文章地址:http://blog.csdn.net/topasstem8/article/details/6735240

PHP并没有完善的线程支持,甚至部署到基于线程模型的httpd服务器都会产生一些问题,但即使是多进程模型下的PHP,也难免出现多进程共同访问同一 资源的情况。比如整个程序共享的数据缓存,或者因为资源受限而必须对特定处理过程进行排队,以及针对每个用户生成唯一的某种标识的情形。PHP语言自身没 有提供进程互斥和锁定机制,因而使得在这些情况下的编程遇到了困难,目前了解到的可选的办法有以下这些:

1、利用MySQL的锁定机制来实现互斥。缺点是增大了数据库服务器的连接负担,并且使得程序依赖于数据库服务才能正常工作。
2、利用文件锁机制。也就是利用flock函数通过文件实现锁定和互斥机制,来模拟通用编程模型下的锁定原语的工作方式。这种方式在以前以纯文本文件为存储引擎的时代成为保护数据完整性的必备元素,现在在使用文本文件作为缓存媒介的场合也相当常见。PmWiki应该也是使用了这个机制来对多人同时编辑一个页面的情形进行提醒。不过文件锁机制多少会调用到宿主操作系统上的文件锁特性,因此在使用时一定要检查服务器操作系统是否为PHP环境提供了完善可靠的文件锁机制。
3、利用共享内存空间计数。PHP可以利用shmop_open函数开辟一块内存空间,在服务进程之间共享数据,为了保证共享数据的互斥安全访问,可以使用 sem_get、sem_acquire和sem_release这组函数实现共享计数锁定机制。这种办法在后台实际是调用了系统的ipc 服务来实现。

用 PHP 编写支持高并发的网站,需要做什么处理?

文章地址:http://www.zhihu.com/question/20049768

1、Webserver (Nginx) :这一层是可以轻松分布式部署的,结合智能DNS解析可以简易地防止单点故障、实现区域访问加速,结合LVS很容易实现负载均衡。这一层主要是负责处理静态请求和转发PHP请求至第二层的PHP处理节点,至于静态资源地址(http://misc.xxxx.com)可以单独拿出来部署,或者直接使用商用的云存储服务(国内七牛不错,国外有Amazon S3)
2、PHP 处理节点:一个节点其实就是一个监听特定端口的系统进程,webserver的请求通过负载均衡器(我用的AWS的loadbalancer)进行分发, 很好实现分布式和负载均衡。我现在用的还是php自带的php-fpm,其实facebook出的hhvm性能非常强悍,但是还不能100%通过我项目的 单元测试,等hhvm成熟过后可以平滑替换
3、高速缓存:用的memcached,这一层的作用主要是减轻数据库IO和加快热数据 访问,缓存策略与程序耦合度较高,不赘述,但简单地说有两种方式,一种是在程序的全局层面加一个缓存处理,这种方法代码耦合度低,但是有效命中率不高,有 些项目不一定适应,另一种是在具体的数据存取处加缓存处理,这种办法程序耦合度较高,但是缓存命中率非常高,几乎没有无效缓存存在,我用的是这种。
4、数据库 :我现在的项目数据规模不大,暂时只用了单台数据库,但是程序逻辑上已做好了数据库线性扩展的准备。其实数据库层的扩展是老生常谈了,常用手段是分库分 表,这一块需要在前期的代码就打下基础,另外更平滑地手段是使用中间件,比如360的Atlas,阿里巴巴的cobar,淘宝的TDDL,中间件可以在不 大范围变更代码的情况下扩展,但是具体的使用场景还是有限的,具体项目还需单独考察。
5、其 他:根据不同的项目,架构还可以选择性地使用队列,我现在用的beantalkd,Redis也是一个很好的选择。队列常用的使用环境是邮件发送和站内消息推送上面,但是在某些场景下也可以作为核心数据库的缓冲,对应对大并发或者突发性流量也是不错的选择

时间: 2025-01-02 05:52:39

并发下常见的加锁及锁的PHP具体实现-转载的相关文章

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

http://www.cnblogs.com/scotoma/archive/2010/09/26/1836312.html Apache + PHP 的并发访问 http://www.cnblogs.com/WestContinent/archive/2013/03/25/2981667.html 4.结论 从上面的试验结果可以得到如下结论,因为两组测试数据中的时间犬牙交错,两个用户在耗时操作中并没有出现某一个用户长时间占用执行时间片的情况.说明Apache+Php(loadmodule)是支

常见的几种锁

1.悲观锁  for update 悲观锁认为每次查询数据数据都会造成数据的更新或者丢失问题,所以每次查询都会加上排它锁. 如图所示,当两条线程同时访问该sql语句时,可能会造成脏读数据user_money为原来的两倍(假设线程一执行完第一句等待,线程二将两句全部执行完,这时线程一如果继续执行则会脏读数据) 使用悲观锁则通过在其后加for update后,仅允许一个连接查询数据也就是只要一个连接获得锁后,其他连接则只能等待该锁的释放. 缺点:每次都只有一个连接进行操作,效率非常低,适合查询量低的

iOS - 互斥锁&amp;&amp;自旋锁 多线程安全隐患(转载)

一.多线程安全隐患 资源共享  一块资源可能会被多个线程共享,也就是多个线程可能会访问到一块资源 比如多个线程访问同一个对象,同一个变量,同一个文件. 当多线程访问同一块资源的时候,很容易引发数据错乱和数据安全问题二.原子和非原子属性 1>OC 在定义属性的时候有nonatomic和atomic两种选择      * atomic:原子属性,为 setter 方法加锁      * nonatomic:非原子属性,不会为 setter 方法加锁        普通情况下都是在主线程做操作,所以一

mysql乐观锁总结和实践(转载)

原文地址:http://chenzhou123520.iteye.com/blog/1863407 乐观锁介绍: 乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做.那么我们如何实现乐观锁呢,一般来说有以下2种方式: 1.使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式.何谓数据版本?即为数

机器学习常见算法个人总结(面试用)【转载】

朴素贝叶斯 参考[1] 事件A和B同时发生的概率为在A发生的情况下发生B或者在B发生的情况下发生AP(A∩B)=P(A)∗P(B|A)=P(B)∗P(A|B) 所以有:P(A|B)=P(B|A)∗P(A)P(B) 对于给出的待分类项,求解在此项出现的条件下各个目标类别出现的概率,哪个最大,就认为此待分类项属于哪个类别 工作原理 假设现在有样本x=(a1,a2,a3,…an)这个待分类项(并认为x里面的特征独立) 再假设现在有分类目标Y={y1,y2,y3,y4..yn} 那么max(P(y1|x

IE6 浏览器常见兼容问题 大汇总(23个)[转载]

IE6以及各个浏览器常见兼容问题 大汇总 综述:虽然说IE6在2014年4月将被停止支持,但是不得不说的是,IE6的市场并不会随着支持的停止而立刻消散下去,对于WEB前端开发工程师来说,兼容IE6 兼容各个浏览器,依然是不得不面对的工作. 在此总结了常见的浏览器兼容问题,里面也有IE6的常见兼容问题,供大家分享. 1.<!DOCTYPE HTML>文档类型的声明. 产生条件:IE6浏览器,当我们没有书写这个文档声明的时候,会触发IE6浏览器的怪异解析现象: 解决办法:书写文档声明. 2.不同浏

Runtime简介以及常见的使用场景(此内容非原创,为转载内容)

Runtime简称运行时,是一套比较底层的纯C语言的API, 作为OC的核心,运行时是一种面向对象的编程语言的运行环境,其中最主要的是消息机制,Objective-C 就是基于运行时的. 所谓运行时,是指尽可能地把决定从编译期推迟到运行期,就是尽可能地做到动态.只是在运行的时候才会去确定对象的类型和方法的.因此利用Runtime机制可以在程序运行时动态地修改类和对象中的所有属性和方法. 对于C语言,函数的调用在编译的时候会决定调用哪个函数.对于OC的函数,属于动态调用过程,在编译的时候并不能决定

关于redis分布式锁的实现方式(转载)

这个是在网上找到的一个大神写的(http://wudashan.cn/2017/10/23/Redis-Distributed-Lock-Implement/),对于分布式redis部署的,可以参考redisson(https://github.com/redisson/redisson/tree/master/redisson/src/main/java/org/redisson)

PHP开发的一些注意点总结

技术平台的不同,导致了实现方式的不同,同样是PHP(PHP培训 php教程 ),小公司往往选择的是WIN平台而大公司选择的是类unix平台(Linux,FreeBSD and Other) ,现在就最近这段时间的学习,这好乘国庆长假这段时间好好的总结下的了. Linux系统的使用 现在标配的系统是 Linux + Nginx + PHP + MySQL ,这样的配置越来越多的大公司在用的了说到配置不同的是一个公司的规约,比如说挂载一般分为2个盘, / 下面划分为系统用的分区10G 足够 剩余空间