首頁  >  文章  >  後端開發  >  多級分銷對接第三方API取得資料系統的最佳化

多級分銷對接第三方API取得資料系統的最佳化

WBOY
WBOY原創
2016-08-08 09:20:201325瀏覽

最近在做一個基於有讚的多級分銷管理系統,所有成員的店面均在有讚商城,使用有讚API獲得他們的業績,但是有讚提供的分銷只有一級,故製作該系統。考慮到減輕工作量,理清層次關係,採用了OOP設計方法,將資料庫,表封裝為基類,分銷成員,店面等繼承表。

但是在列出銷售量報表和分銷商的時候出現了嚴重性能問題,由於分銷商的業績獎勵是與其下級分銷商掛鉤的,故封裝數據庫的時候,進行了DFS遍歷來獲得所有分銷商的關係樹,然而,在列出銷售報表的時候卻並不需要這樣的關係,DFS在php語言上的時間花銷極大,導致一個頁面打開需要10s以上的時間,故對其進行第一步優化,在資料庫的封裝函數中設定DFS開關:

這個是Database類別的部分實現,其中部分敏感資料已隱藏。

<?php
namespace System;
require_once(&#39;KdtApiClient.php&#39;);
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物件的實現如下,將物件的序列化程式碼存於伺服器本地:

<?php
	namespace 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[&#39;time&#39;]>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類別的回饋選擇取得本地資料,或是要求伺服器更新本地數據:

<?php
require_once(&#39;System/db.php&#39;);
require_once(&#39;System/cache.php&#39;);
use \System\Database;
use \System\Cache;

switch($_GET[&#39;action&#39;])
{
	case &#39;num&#39;:
		$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左右.

版權聲明:本文為博主原創文章,未經博主允許不得轉載。

以上就介紹了多級分銷對接第三方API取得資料系統的最佳化,包含了面向的內容,希望對PHP教學有興趣的朋友有所幫助。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn