请选择 进入手机版 | 继续访问电脑版
绿茶科技社区
用到了Eaccelerator的内存锁 和 文件锁,原理如下判断系统中是否安了EAccelerator 如果有则使用内存锁,如果不存在,则进行文件锁
在最近的项目中有这样的场景
1.生成文件的时候,由于多用户都有权限进行生成,防止并发下,导致生成的结果出现错误,需要对生成的过程进行加锁,只容许一个用户在一个时间内进行操作,这个时候就需要用到锁了,将这个操作过程锁起来.
2.在用了cache的时候,cache失效可能导致瞬间的多数并发请求穿透到数据库此时也可以得需要用锁在同一并发的过程中将这个操作锁定.

针对以上的2种情况,现在的解决方法是对处理过程进行锁机制,通过PHP实现如下
用到了Eaccelerator的内存锁 和 文件锁,原理如下
判断系统中是否安了EAccelerator 如果有则使用内存锁,如果不存在,则进行文件锁
根据带入的key的不同可以实现多个锁直接的并行处理,类似Innodb的行级锁

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

  1. <?php
  2. /**
  3. * CacheLock 进程锁,主要用来进行cache失效时的单进程cache获取,防止过多的SQL请求穿透到数据库
  4. * 用于解决PHP在并发时候的锁控制,通过文件/eaccelerator进行进程间锁定
  5. * 如果没有使用eaccelerator则进行进行文件锁处理,会做对应目录下产生对应粒度的锁
  6. * 使用了eaccelerator则在内存中处理,性能相对较高
  7. * 不同的锁之间并行执行,类似mysql innodb的行级锁
  8. * 本类在sunli的phplock的基础上做了少许修改 http://code.google.com/p/phplock
  9. * @author yangxinqi
  10. *
  11. */
  12. class CacheLock
  13. {
  14. //文件锁存放路径
  15. private $path = null;
  16. //文件句柄
  17. private $fp = null;
  18. //锁粒度,设置越大粒度越小
  19. private $hashNum = 100;
  20. //cache key
  21. private $name;
  22. //是否存在eaccelerator标志
  23. private $eAccelerator = false;
  24. /**
  25. * 构造函数
  26. * 传入锁的存放路径,及cache key的名称,这样可以进行并发
  27. * @param string $path 锁的存放目录,以"/"结尾
  28. * @param string $name cache key
  29. */
  30. public function __construct($name,$path='lock\\')
  31. {
  32. //判断是否存在eAccelerator,这里启用了eAccelerator之后可以进行内存锁提高效率
  33. $this->eAccelerator = function_exists("eaccelerator_lock");
  34. if(!$this->eAccelerator)
  35. {
  36. $this->path = $path.($this->_mycrc32($name) % $this->hashNum).'.txt';
  37. }
  38. $this->name = $name;
  39. }
  40. /**
  41. * crc32
  42. * crc32封装
  43. * @param int $string
  44. * @return int
  45. */
  46. private function _mycrc32($string)
  47. {
  48. $crc = abs (crc32($string));
  49. if ($crc & 0x80000000) {
  50. $crc ^= 0xffffffff;
  51. $crc += 1;
  52. }
  53. return $crc;
  54. }
  55. /**
  56. * 加锁
  57. * Enter description here ...
  58. */
  59. public function lock()
  60. {
  61. //如果无法开启ea内存锁,则开启文件锁
  62. if(!$this->eAccelerator)
  63. {
  64. //配置目录权限可写
  65. $this->fp = fopen($this->path, 'w+');
  66. if($this->fp === false)
  67. {
  68. return false;
  69. }
  70. return flock($this->fp, LOCK_EX);
  71. }else{
  72. return eaccelerator_lock($this->name);
  73. }
  74. }
  75. /**
  76. * 解锁
  77. * Enter description here ...
  78. */
  79. public function unlock()
  80. {
  81. if(!$this->eAccelerator)
  82. {
  83. if($this->fp !== false)
  84. {
  85. flock($this->fp, LOCK_UN);
  86. clearstatcache();
  87. }
  88. //进行关闭
  89. fclose($this->fp);
  90. }else{
  91. return eaccelerator_unlock($this->name);
  92. }
  93. }
  94. }
复制代码
本类在孙立同学的类的基础上做了小点改进的了.具体可以看 http://code.google.com/p/phplock感谢孙同学的分享精神!



分享到 :
0 人收藏

2 个回复

倒序浏览
EtherDream  高级会员 | 2019-9-27 02:13:33
不错 支持下
邀月  高级会员 | 2019-10-9 09:06:06
路过 帮顶 嘿嘿
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

举报|Archiver|手机版|小黑屋|Lvchakeji Inc.  

Powered by Discuz! X3.3 © 2001-2016 Comsenz Inc.

返回顶部