日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

Laravel解決高并發(fā)問題的思路

作者:王中陽(yáng) 更新時(shí)間: 2022-09-22 編程語(yǔ)言

問題復(fù)現(xiàn)

客戶端并發(fā)請(qǐng)求扣費(fèi)接口,導(dǎo)致重復(fù)扣費(fèi);
服務(wù)端的加鎖邏輯不正確,鎖加到了非核心邏輯上,即加到了消費(fèi)記錄表,而不是加到了核心業(yè)務(wù)表。

有問題的代碼

  1. 首次進(jìn)入聊天房則扣費(fèi),再次進(jìn)入不重復(fù)扣費(fèi)
  2. 這個(gè)思路無法規(guī)避并發(fā)問題
    public function agoraToken(Request $request)
    {
        .
        .
        .
            try {
                DB::connection('footprint')->beginTransaction();
                if ($this->_userid == $appointmentInfo->userid) {
                    //如果已經(jīng)存在則不重復(fù)扣費(fèi) 但是并發(fā)問題會(huì)導(dǎo)致重復(fù)扣費(fèi)
                    if (!AppointmentAction::existAction($this->_userid, $request->appointmentId, AppointmentAction::TYPE_ACTION_ENTER)) {
                        $propCount = UserConsume::getAppointmentSendConsumeCouponCount($this->_userid, $request->otherUserid);
                        $userConsume = new UserConsume($this->_userid);
                        Log::error("營(yíng)業(yè)中約會(huì) \n消費(fèi)啤酒個(gè)數(shù):" . $propCount . " \n用戶id:" . $this->_userid . " \n對(duì)方id:" . $request->otherUserid . " \n時(shí)間戳:" . time());
                        $userConsume->consumeCommon(CouponInfo::PROP_COUPON_CHAMPAGNE_ID, PropInfo::PROP_CHAMPAGNE_ID, $propCount);
                        DB::connection('footprint')->commit();
                    }
                }
                
                //記錄進(jìn)入房間
                AppointmentAction::record($this->_userid, $request->appointmentId, AppointmentAction::TYPE_ACTION_ENTER);
            } catch (\Exception $exception) {
                Log::error("扣費(fèi)失敗:" . $exception);
                DB::connection('footprint')->rollBack();
            }
        .
        .
        .
    }

優(yōu)化后的代碼

  1. 引入事務(wù),引入try catch
  2. 查詢約會(huì)數(shù)據(jù)加鎖,當(dāng)未扣費(fèi)時(shí)扣費(fèi),已扣費(fèi)則修改扣費(fèi)狀態(tài)
  3. 修改扣費(fèi)狀態(tài)成功提交事務(wù),釋放鎖
  4. 扣費(fèi)失敗回滾事務(wù)
    public function agoraToken(Request $request)
    {
        .
        .
        .
        //try catch 捕獲異常,避免崩潰
            try {
                //開啟事務(wù) 因?yàn)橹皇鞘聞?wù)中的鎖才生效 鎖包括lockForUpdate()和sharedLock()
                DB::connection('footprint')->beginTransaction();
                //校驗(yàn)獲取token的合法性
                $appointmentInfo = AppointmentInfo::query()->selectRaw('id,userid,"inviteeUserid","prepareId",status,"isConsume"')
                    ->where('id', $request->appointmentId)->lockForUpdate()->first();
                if (empty($appointmentInfo) || !in_array($this->_userid, [$appointmentInfo->inviteeUserid, $appointmentInfo->userid])) {
                    return ErrorCode::TYPE_ILLEGAL_REQUEST;
                }
   
                //這里是關(guān)鍵 根據(jù)isConsume標(biāo)記是否扣費(fèi)了
                if ($appointmentInfo->isConsume == AppointmentInfo::TYPE_IS_NOT_CONSUME) {
                    $propCount = UserConsume::getAppointmentSendConsumeCouponCount($this->_userid, $request->otherUserid);
                    $userConsume = new UserConsume($this->_userid);
                    Log::error("營(yíng)業(yè)中約會(huì),個(gè)數(shù):" . $propCount . " 用戶id:" . $this->_userid . ' 對(duì)方id:' . $request->otherUserid);
                    $userConsume->consumeCommon(CouponInfo::PROP_COUPON_CHAMPAGNE_ID, PropInfo::PROP_CHAMPAGNE_ID, $propCount);
                    //消費(fèi)成功后修改isConsume的值,提交事務(wù)
                    $appointmentInfo->isConsume = AppointmentInfo::TYPE_IS_CONSUME;
                    $appointmentInfo->save();
                    DB::connection('footprint')->commit();
                }
                .
                .
                .
            } catch (\Exception $exception) {
                //異常情況打印log 回滾事務(wù)
                Log::error("約會(huì)扣費(fèi)異常:" . \GuzzleHttp\json_encode($exception));
                DB::connection('footprint')->rollBack();
            }
        .
        .
        .
    }

期間的嘗試和思考

  1. 要給核心邏輯加鎖,進(jìn)入聊天房只是一種記錄,而不是核心邏輯,不能作為鎖定條件

原文鏈接:https://blog.csdn.net/w425772719/article/details/120237037

欄目分類
最近更新