多級分銷對接第三方API擷取資料系統的最佳化,第三方api
最近在做一個基於有贊的多級分銷管理系統,所有成員的店面均在有贊商城,使用有贊API獲得他們的業績,但是有贊提供的分銷只有一級,故製作該系統。考慮到減輕工作量,理清層次關係,採用了OOP設計方法,將資料庫,表封裝為基類,分銷成員,店面等繼承表。
但是在列出銷售量報表和分銷商的時候出現了嚴重性能問題,由於分銷商的業績獎勵是與其下級分銷商掛鈎的,故封裝資料庫的時候,進行了DFS遍曆來獲得所有分銷商的關係樹,然而,在列出銷售報告的時候卻並不需要這樣的關係,DFS在php語言上的時間花銷極大,導致一個頁面開啟需要10s以上的時間,故對其進行第一步最佳化,在資料庫的封裝函數中設定DFS開關:
這個是Database類的部分實現,其中部分敏感性資料已隱藏。
<?phpnamespace System;require_once('KdtApiClient.php');class Database{const db_adr="";const db_usr="";const db_pwd="";const db_db="";public $member=array();public function init($dfs=true,$store=true){$mysqli=new \mysqli(self::db_adr,self::db_usr,self::db_pwd,self::db_db);if($mysqli->connect_error) throw new Exception('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);$result=$mysqli->query("select `id` from member_new");$row=$result->fetch_array();$i=0;while($row){$this->member[$i]=new Member($row[0],$dfs,$store);$row=$result->fetch_array();$i++;}$mysqli->close();}static public function doQuery($string){$mysqli=new \mysqli(self::db_adr,self::db_usr,self::db_pwd,self::db_db);if($mysqli->connect_error) throw new Exception('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);return $mysqli->query($string);}static public function querySell($start,$end) {}}
member類是繼承自Table:
class Table{public $data=array();protected $table_name;public function __construct($id){$this->data['id']=$id;$mysqli=new \mysqli(Database::db_adr,Database::db_usr,Database::db_pwd,Database::db_db);if($mysqli->connect_error) throw new Exception('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);$result=$mysqli->query("select * from ".$this->table_name." where `id`=$id");$row=$result->fetch_assoc();$this->data=$row;$mysqli->close();}public function updateAll()//Do NOT CHANGE ID!!!{reset($this->data);while($data=each($this->data)){$querystring="update ".$this->table_name." set `".$data[0]."`='$data[1]' where `id`='".$this->data['id']."'";Database::doQuery($querystring);}reset($this->data);}public function update($key){$querystring="update ".$this->table_name." set `$key`='".$this->data[$key]."' where `id`='".$this->data['id']."'";Database::doQuery($querystring);}public function set($key,$data)//recommended{$this->data[$key]=$data;$this->update($key);}public function get($key)//recommended{return $this->data[$key];}}
封裝了對錶的基本操作,簡化以後的代碼編寫.下面member類的建構函式可以完成DFS功能,加設切換參數後,可以在某些場合不試用DFS而大大提升效率:
class Member extends Table{protected $table_name="member_new";public $infer=array();public $store=array();public function __construct($id,$dfs=true,$store=true){parent::__construct($id);$mysqli=new \mysqli(Database::db_adr,Database::db_usr,Database::db_pwd,Database::db_db);if($mysqli->connect_error) throw new Exception('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);if($dfs){$result=$mysqli->query("select `id` from ".$this->table_name." where `super`=".$this->data['id']);if($result){$row=$result->fetch_array();$i=0;while($row){$this->infer[$i]=new Member($row[0]);$row=$result->fetch_array();$i++;}}}if($store){$result=$mysqli->query("select `id` from store_new where `member`=".$this->data['id']);if($result){$row=$result->fetch_array();$i=0;while($row){$this->store[$i]=new Store($row[0]);$row=$result->fetch_array();$i++;}}}$mysqli->close();}
(部分敏感函數已隱藏)
另外,在對前端的AJAX響應的php指令碼中,加入緩衝的支援,由於有贊的api調用速度較慢,然而這種分銷商城的資料對即時性的要求並不是很高,故採用伺服器緩衝的方式來減少與有贊通訊這部分導致的速度減緩.另外,本地化的對象代替從遠端資料庫讀取資訊,也減少了查詢資料庫的開支.Cache對象的實現如下,將對象的序列化代碼存於伺服器本地:
<?phpnamespace System; class Cache { public function __construct() { } static public function readCache($string) {error_reporting(1); $file=fopen($string.".ser","r"); if(!$file)return false; $ser=fread($file,filesize($string.".ser")); fclose($file); $array=array(); $array=unserialize($ser); if(time()-$array['time']>3600*24)return false; return $array['data']; } static public function updateCache($string,$data) { $array=array(); $array['time']=time(); $array['data']=$data; $file=fopen($string.".ser","w"); fwrite($file,serialize($array)); fclose($file); } }
後端AJAX響應頁面根據Cache類的反饋選擇擷取本機資料,或是請求伺服器更新本機資料:
<?phprequire_once('System/db.php');require_once('System/cache.php');use \System\Database;use \System\Cache;switch($_GET['action']){case 'num':$result=Database::doQuery("select count(*) from member_new");$row=$result->fetch_array();echo $row[0];exit(0);case 'get':if($array=Cache::readCache("member")){echo json_encode($array);}else{$db=new Database();$db->init(false,true);$arr=array();for($i=0;$i<count($db->member);$i++){$arr[$i]=array();$arr[$i]=$db->member[$i]->data;$arr[$i]['password']=null;$arr[$i]['name']=iconv("GBK","utf-8",$arr[$i]['name']);$arr[$i]['nickname']=iconv("GBK","utf-8",$arr[$i]['nickname']);$arr[$i]['sell']=$db->member[$i]->getSell();}Cache::updateCache("member",$arr);echo json_encode($arr);}exit(0);
經過以上最佳化,原本回應時間在15s左右的頁面,現在回應時間為0.5s左右.
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。