DDR爱好者之家 Design By 杰米

在工作项目中,会遇到一些php并发访问去修改一个数据问题,如果这个数据不加锁,就会造成数据的错误。下面我将分析一个财务支付锁的问题。希望对大家有所帮助。

1 没有应用锁机制

1.1 财务支付简化版本代码

<!--"select account form user_account where userid = ${userId}";
  
 //$mysql = new mysql();//mysql数据库
 return $mysql->query($sql);
}
 
//更新用户余额
function setUserLeftMoney($userId,$money)
{
 if(false == is_int($userId) || false == is_int($money))
 {
  return false;
 }  
  
 $sql = "update user_account set account = ${money} where userid = ${userId}";
  
 //$mysql = new mysql();//mysql数据库
 return $mysql->execute($sql);
}
"//img.jbzj.com/file_images/article/201610/2016101791936217.png" alt="" />

2.2 php源码设计如下

LockSystem.php

<!--"not support lock of ${type}");
  }
  $this->_lock = new $type($options);
 }  
 public function getLock($key, $timeout = ILock::EXPIRE)
 {
  if (false == $this->_lock instanceof ILock) 
  {
   throw new Exception('false == $this->_lock instanceof ILock');   
  } 
  $this->_lock->getLock($key, $timeout); 
 }
  
 public function releaseLock($key)
 {
  if (false == $this->_lock instanceof ILock) 
  {
   throw new Exception('false == $this->_lock instanceof ILock');   
  } 
  $this->_lock->releaseLock($key);   
 } 
}
interface ILock
{
 const EXPIRE = 5;
 public function getLock($key, $timeout=self::EXPIRE);
 public function releaseLock($key);
}
 
class FileLock implements ILock
{
 private $_fp;
 private $_single;
 
 public function __construct($options)
 {
  if (isset($options['path']) && is_dir($options['path']))
  {
   $this->_lockPath = $options['path'].'/';
  }
  else
  {
   $this->_lockPath = '/tmp/';
  }
  
  $this->_single = isset($options['single'])"w+");
  if (true || $this->_single)
  {
   $op = LOCK_EX + LOCK_NB;
  }
  else
  {
   $op = LOCK_EX;
  }
  if (false == flock($this->fp, $op, $a))
  {
   throw new Exception('failed');
  }
  
  return true;
 }
 public function releaseLock($key)
 {
  flock($this->fp, LOCK_UN);
  fclose($this->fp);
 }
}
 
class SQLLock implements ILock
{
 public function __construct($options)
 {
  $this->_db = new mysql(); 
 }
 
 public function getLock($key, $timeout=self::EXPIRE)
 {  
  $sql = "SELECT GET_LOCK('".$key."', '".$timeout."')";
  $res = $this->_db->query($sql);
  return $res;
 }
 
 public function releaseLock($key)
 {
  $sql = "SELECT RELEASE_LOCK('".$key."')";
  return $this->_db->query($sql);
 }
}
 
class MemcacheLock implements ILock
{
 public function __construct($options)
 {
   
  $this->memcache = new Memcache();
 }
 
 public function getLock($key, $timeout=self::EXPIRE)
 {  
  $waitime = 20000;
  $totalWaitime = 0;
  $time = $timeout*1000000;
  while ($totalWaitime < $time && false == $this->memcache->add($key, 1, $timeout)) 
  {
   usleep($waitime);
   $totalWaitime += $waitime;
  }
  if ($totalWaitime >= $time)
   throw new Exception('can not get lock for waiting '.$timeout.'s.');
 
 }
 
 public function releaseLock($key)
 {
  $this->memcache->delete($key);
 }
}

3 应用锁机制

3.1 支付系统应用锁

<!--"select account form user_account where userid = ${userId}";
  
 //$mysql = new mysql();//mysql数据库
 return $mysql->query($sql);
}
 
//更新用户余额
function setUserLeftMoney($userId,$money)
{
 if(false == is_int($userId) || false == is_int($money))
 {
  return false;
 }  
  
 $sql = "update user_account set account = ${money} where userid = ${userId}";
  
 //$mysql = new mysql();//mysql数据库
 return $mysql->execute($sql);
}
?>

3.2 锁分析

p操作人:

  1.  获取锁:pay100
  2.  取出用户的余额1000。
  3.  支付后剩余 800 = 1000 - 200。
  4.  更新后账户余额800。
  5.  释放锁:pay100

 m操作人:

  1. 等待锁:pay100
  2. 获取锁:pay100
  3. 获取余额:800
  4. 支付后剩余500 = 800 - 300。
  5. 支付后账户余额500。
  6. 释放锁:pay100

两次支付后,余额500。非常完美了解决了并发造成的临界区资源的访问问题。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米

P70系列延期,华为新旗舰将在下月发布

3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。

而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?

根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。