php併發加鎖以支付為例

2021-08-21 17:28:35 字數 4324 閱讀 1789

本文介紹了php併發加鎖示例,對資料進行加鎖,只容許乙個使用者在乙個時間內進行操作,這個時候就需要用到鎖了,需要的朋友可以了解一下。

在工作專案中,會遇到一些php併發訪問去修改乙個資料問題,如果這個資料不加鎖,就會造成資料的錯誤。下面我將分析乙個財務支付鎖的問題。希望對大家有所幫助。

1 沒有應用鎖機制

1.1 財務支付簡化版本**

<?php  

/** 

* pay.php 

* * 支付沒有應用鎖

* * copy right (c) 2016 

* * modification history: 

* -------------------- 

* 2016/9/10, by clevercode, create 

* */

//使用者支付

function pay($userid,$money)

//取出總額

$total = getuserleftmoney($userid);   

//花費大於剩餘

if($money --> $total)

//餘額

$left = $total - $money;

//更新餘額

return setuserleftmoney($userid,$left);

}//取出使用者的餘額

function getuserleftmoney($userid)

$sql = "select account form user_account where userid = $";

//$mysql = new mysql();//mysql資料庫

return $mysql->query($sql);

}//更新使用者餘額

function setuserleftmoney($userid,$money)

$sql = "update user_account set account = $ where userid = $";

//$mysql = new mysql();//mysql資料庫

return $mysql->execute($sql);

}?>

1.2 問題分析如果有兩個操作人(p和m),都用使用者編號100賬戶,分別在pc和手機端同時登陸,100賬戶總餘額有1000,p操作人花200,m操作人花300。併發過程如下。

p操作人:

取出使用者的餘額1000。

支付後剩餘 800 = 1000 - 200。

更新後賬戶餘額800。

m操作人:

取出使用者餘額1000。

支付後剩餘700 = 1000 - 300。

支付後賬戶餘額700。

兩次支付後,賬戶的餘額居然還有700,應該的情況是花費了500,賬戶餘額500才對。造成這個現象的根本原因,是併發的時候,p和m同時操作取到的餘額資料都是1000。

2 加鎖設計

鎖的操作一般只有兩步,一 獲取鎖(getlock);二是釋放鎖(releaselock)。但現實鎖的方式有很多種,可以是檔案方式實現;sql實現;memcache實現;根據這種場景我們考慮使用策略模式。

2.1 類圖設計如下

2.2 php原始碼設計如下

locksystem.php

<?php  

/** 

* locksystem.php 

* * php鎖機制

* * copy right (c) 2016

* * modification history: 

* -------------------- 

* 2016/9/10, by clevercode, create 

* */

class locksystem

} public function createlock($type, $options=array())

");}

$this->_lock = new $type($options);

}  public function getlock($key, $timeout = ilock::expire)

$this->_lock->getlock($key, $timeout); 

}public function releaselock($key)

$this->_lock->releaselock($key);   } }

inte***ce ilock

class filelock implements ilock

else

$this->_single = isset($options['single'])?$options['single']:false;

}public function getlock($key, $timeout=self::expire)

else

if (false == flock($this->fp, $op, $a))

return true;

}public function releaselock($key)

}class sqllock implements ilock

public function getlock($key, $timeout=self::expire)

public function releaselock($key)

}class memcachelock implements ilock

public function getlock($key, $timeout=self::expire)

if ($totalwaitime >= $time)

throw new exception('can not get lock for waiting '.$timeout.'s.');

}public function releaselock($key)

3 應用鎖機制3.1 支付系統應用鎖

<?php

/** 

* pay.php 

* * 支付應用鎖

* * copy right (c) 2016 

* * modification history: 

* -------------------- 

* 2016/9/10, by clevercode, create 

* */

//使用者支付

function pay($userid,$money)

tryelse

//釋放鎖

$locksystem->releaselock($lockkey); 

}catch (exception $e)

}//取出使用者的餘額

function getuserleftmoney($userid)

$sql = "select account form user_account where userid = $";

//$mysql = new mysql();//mysql資料庫

return $mysql->query($sql);

}//更新使用者餘額

function setuserleftmoney($userid,$money)

$sql = "update user_account set account = $ where userid = $";

//$mysql = new mysql();//mysql資料庫

return $mysql->execute($sql);

}?>

3.2 鎖分析p操作人:

獲取鎖:pay100

取出使用者的餘額1000。

支付後剩餘 800 = 1000 - 200。

更新後賬戶餘額800。

釋放鎖:pay100

m操作人:

等待鎖:pay100

獲取鎖:pay100

獲取餘額:800

支付後剩餘500 = 800 - 300。

支付後賬戶餘額500。

釋放鎖:pay100

兩次支付後,餘額500。非常完美了解決了併發造成的臨界區資源的訪問問題。

php併發加鎖

clevercode在工作專案中,會遇到一些php併發訪問去修改乙個資料問題,如果這個資料不加鎖,就會造成資料的錯誤。下面clevercode將分析乙個財務支付鎖的問題。1.1 財務支付簡化版本 pay.php 支付沒有應用鎖 copy right c 2016 modification histo...

debug幾法(以PHP為例)

例如,我先寫一段 echo5 0 這樣一定會出錯的,因為0不能做除數。頁面上顯示 php會直接輸出這個除以0的致命錯誤的資訊。當我們執行乙個很長的過程時出現了邏輯上的錯誤 語法上並沒有錯誤,這種bug比較難解決 一時沒有頭緒,不妨先試著輸出每個過程的執行結果,看看到底哪一步的執行脫離了預想的設計。這...

php擴充套件編譯(以memcached為例)

2 解壓並切換進入擴充套件包的目錄 3 使用phpize工具自動生成 configure 4 configure配置擴充套件 5 編譯並安裝擴充套件 下面以編譯php的memcached擴充套件來做乙個 參考 編譯memcached需要libmemcached庫,所以我們先安裝一下libmemcac...