【PHP】PHP程式碼處理(普通/不重要的)併發情況,例如pv統計(不使用MySQL行或表鎖、避免程式冗餘)
阿新 • • 發佈:2020-11-09
1、PHP程式碼處理(普通/不重要的)併發情況,例如統計pv資料:什麼意思呢?
比如pv統計,某時間段pv資料不存在則新增,存在則更新+1,這時候會存在一個問題:我們查詢的時候可能沒有記錄,但是準備插入的時候卻已經有資料了(別的程序捷足先登)
解決辦法:我們可以在MySQL設定 唯一主鍵,配合php程式碼進行控制,使用 try catch 捕獲MySQL的異常,匹配異常程式碼,將重複的一行進行更新
/** * 頁面pv統計 */ public function statPv(Request $request) { $node_id = $request->node_id ?? config('cache.master_node_id'); $openId = $request->input('open_id'); $event = Input::get('event') ?? ''; $route = Input::get('route') ?? ''; $data = S::show($route); if($event != 'show'){ return S::jsonReturn( ['info'=>'fail~~'] ); } $sessionKey = $request->input('3rd_session'); if(empty($openId) || empty($sessionKey)){ return S::jsonReturn( ['info'=>'fail'] ); } $userInfo = unserialize(WeChatDao::baseRedis('get', ':' . $openId . '_cache')); $sysSessionKey = unserialize(WeChatDao::baseRedis('get', ':key:' . md5($sessionKey))); if(empty($sysSessionKey)){ return S::jsonReturn( ['info'=>'fail~'] ); } if(empty($userInfo)){ return S::jsonReturn( ['info'=>'fail!'] ); } if ($userInfo['open_id'] != $sysSessionKey['openid']) { return S::jsonReturn( ['info'=>'fail!!'] ); } $url = $data['path']; $query = $data['query']; $trans_date = date('Y-m-d'); $trans_hour = date('H') . ':00'; $pvObj = StatPageVisitDay::where('node_id',$node_id)->where('trans_date',$trans_date)->where('trans_hour',$trans_hour)->where('url',$url)->first(); if(!empty($pvObj)) { $pvObj->increment('pv'); } else { $pvObj = new statPageVisitDay(); $pvObj->node_id = $node_id; $pvObj->trans_date = $trans_date; $pvObj->trans_hour = $trans_hour; $pvObj->pv = 1; $pvObj->url = $url; $pvObj->param = $query; try { $pvObj->save(); } catch (\Exception $e) { $message = $e->getMessage(); if (strstr($message, "Duplicate") && strstr($message, "for key ")) { log_write('插入pv表主鍵或唯一索引重複,再次執行更新操作' . $message); StatPageVisitDay::where('node_id',$node_id)->where('trans_date',$trans_date)->where('trans_hour',$trans_hour)->where('url',$url)->increment('pv'); } else { log_write("PV入庫異常,原因{$e->getMessage()}"); MailDao::warning("pv統計異常. 頁面uri={$route},", json_encode(['err_msg'=>$e->getMessage()])); return S::jsonReturn( ['info'=>'statpv insert failed'] ); } } } return S::jsonReturn( ['info'=>'success'] ); }