本篇內容介紹了“PHP并發(fā)如何保證數據的一致性”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
創(chuàng)新互聯公司專業(yè)為企業(yè)提供周村網站建設、周村做網站、周村網站設計、周村網站制作等企業(yè)網站建設、網頁設計與制作、周村企業(yè)網站模板建站服務,十多年周村做網站經驗,不只是建網站,更提供有價值的思路和整體網絡服務。
業(yè)務場景分析
用戶購買商品的邏輯中,需要對用戶錢包的余額進行查詢和扣款。如果同一用戶并發(fā)執(zhí)行多個業(yè)務進行” 查詢 + 扣款” 的業(yè)務中有一定概率出現數據不一致。
Tips:如果沒有做限制單一接口請求頻率,用戶使用并發(fā)請求的手段也有概率出現數據不一致。
1: 從數據庫查詢用戶錢包余額
SELECT balance FROM user_wallet WHERE uid = $uid; +---------+| balance | +---------+| 100 | +---------+1 row in set (0.02 sec)
2: 業(yè)務邏輯
Tips: 文章分享處理同一用戶并發(fā)扣款一致性,檢查庫存啥的邏輯略過
1. 查詢商品價格,比如 70 元
2. 商品價格對比余額是否足夠,足夠時進行扣款提交訂單邏輯
if(goodsPrice <= userBalance) { $newUserBalance = userBalance - goodsPrice; }else { throw new UserWalletException(['msg' => '用戶余額不足']); }
3: 將數據庫的余額進行修改
UPDATE user_wallet SET balance=$newUserBalance WHERE uid = $uid
在沒有并發(fā)的情況下,這個流程沒有任何問題,原有余額 100,購買 70 元的商品,剩余 30 元
1: 用戶并發(fā)購買業(yè)務 A 和業(yè)務 B(不同實例 / 服務),一定概率并行查詢余額是 100
3:
1 業(yè)務 A 先進行修改,修改余額為 30
此時異常出現了,原余額 100 元,業(yè)務 A 和業(yè)務 B 的商品價格總和 150 元(70+80)都購買成功且余額還剩 20 元。
異常點:業(yè)務 A 和業(yè)務 B 并行查詢余額為 100
悲觀鎖
使用 redis 悲觀鎖,例如搶到一個 KEY 才能繼續(xù)操作,否則禁止操作
封裝了一個開箱即用的 RedisLock
<?phpuse Ar414\RedisLock; $redis = new \Redis(); $redis->connect('127.0.0.1','6379'); $lockTimeOut = 5; $redisLock = new RedisLock($redis,$lockTimeOut); $lockKey = 'lock:user:wallet:uid:1001'; $lockExpire = $redisLock->getLock($lockKey);if($lockExpire) { try { //select user wallet balance for uid $userBalance = 100; //select goods price for goods_id $goodsPrice = 80; if($userBalance >= $goodsPrice) { $newUserBalance = $userBalance - $goodsPrice; //TODO set user balance in db }else { throw new Exception('user balance insufficient'); } $redisLock->releaseLock($lockKey,$lockExpire); } catch (\Throwable $throwable) { $redisLock->releaseLock($lockKey,$lockExpire); throw new Exception('Busy network'); } }
樂觀鎖
使用 CAS(Compare And Set)
在 set 寫回的時候,加上初始狀態(tài)的條件 compare, 只有初始狀態(tài)不變的時候才允許 set 寫回成功,保證數據一致性的方法
UPDATE user_wallet SET balance=$newUserBalance WHERE uid = $uid
改為:
UPDATE user_wallet SET balance=$newUserBalance WHERE uid = $uid AND balance = $oldUserBalance
這樣的話并發(fā)操作時只有一個是執(zhí)行成功的,根據 affect rows 是否為 1 判斷是否成功
“PHP并發(fā)如何保證數據的一致性”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯網站,小編將為大家輸出更多高質量的實用文章!
網站欄目:PHP并發(fā)如何保證數據的一致性
瀏覽地址:http://aaarwkj.com/article20/psocco.html
成都網站建設公司_創(chuàng)新互聯,為您提供外貿建站、網站改版、全網營銷推廣、用戶體驗、網站設計公司、定制網站
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯