国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

緩存的使用

2019-11-15 02:03:12
字體:
來源:轉載
供稿:網友
緩存的使用

  緩存,提高訪問速度的利器。工作中主要用到的是memcache和redis,它們是B/S軟件,類似練習時裝在機子上的Apache,它也會監聽端口,可以在客戶端(如在cmd上通過telnet操作Memcache)直接敲各自對應的命令來存取值,自學時可以通過這樣的方式熟悉下原生命令,看看效果。它們常駐內存,得到數據后寫入內存(安裝軟件后會占用一片內存區域),設定數據的過期時間,用到時直接從內存中讀出來,因為是內存所以訪問速度上有數量級的提高。lz曾今寫了個非常簡單的后臺,完全不用緩存那種,那速度我自己看了都忍不住要咆哮:這么慢tm也能叫網頁?!可那時我年幼無知,不會用緩存,當然現在也不見得好到哪兒去,但愿那時前端妹子沒在心里暗自唾罵>3<......

  memcache的使用較簡單,至少從命令上來看是這樣。在memcache中,存儲的方式是key->value,鍵-值對應的方式存儲,類似聯接數組的元素形式,可存儲的類型可以是數字、字符串、數組、對象等,項目中一般會將非字符串(數字可看成是數字字符串)類型的先進行json編碼或者序列化再存入緩存,取出來時則解碼或者反序列化。Memcache是php專門處理memcache緩存的類,封裝的主要方法是get、set、delete、flush、connect、close,即一個緩存必備的獲取、設置、刪除、清空、連接、關閉等。(中括號為可傳參數)

addkey, var, [flag], [expire]添加一個鍵為key、值為var到服務端,可指定過期時間expire,0則永不過期,最長30天
getkey, [flag]從服務端獲取某一或某些元素
deletekey, [timeout]在指定timeout時間內刪除key對應元素,默認timeout為0立即刪除
flush清空,即刪除所有元素
connecthost, [port], [timeout]連接到memcache服務器host主機的port端口,它會在腳本執行完自動關閉,也可主動關閉
close主動關閉memcache服務端連接,但不會關閉pconnect生成的連接
setkey, var, [flag], [expire]存儲鍵為key、值為var的元素到服務端,key存在則覆蓋其值,不存在新add一個
replacekey, var, [flag], [expire]查找鍵為key的元素,以值var替換,查不到會報錯
incrementkey, [value]在鍵為key的元素上增加值value,value默認為1,可能改變原值
decrementkey, [value]在鍵為key的元素上減少值value,value默認為1,可能改變原值
addServerhost, [port], [persistent], [weight], [timeout], ......添加一個memcache服務到連接池(保存多個memcache連接的地方)中,即建立一個到host的連接,port為端口
pconnecthost, [port], [timeout]建立到位于host主機的memcache服務器的持久連接,port為端口,腳本執行完或調用close也無法關閉這種連接

  其中有幾點需要留意下:

  1. set和replace的用法區別:set幾乎任何情況下,當然不是連接都失敗、內存不夠用等硬性原因,都是成功的,replace只是在已經存在的鍵的基礎上進行修改,鍵若不存在不成功;

  2. connect方法建立的連接,要么腳本運行結束自己斷開,要么調用close()方法被斷開掉;

  3. increment或者的decrement方法得到的數永遠是大于或等于0,如果確實計算后得到的值是小于0的則進行轉化,比如int類型,32位上占4字節,則返回的值是(231-1),計算后大于或等于0的直接返回;而元素之類型為非數字(或數字字符串)的,先轉為數字再計算;

  4. 當我們new一個Memcache對象并進行連接時,可以有兩種方式(不討論持久連接),$mem=new Memcache; $mem->connect('127.0.0.1', 11211); 或者使用addserver方法:$mem->addServer('127.0.0.1', 11211); 后者以向已有的連接池中添加一個Memcache服務器連接的方式建立,效果一樣。

  Redis,一款強大的緩存工具,得益于在國內門戶網站中的廣泛使用,功能上在不斷完善,現在有穩定的版本(貌似微軟github上最新64位的release 2.8版本,在我工作的機子上運行不起來...),方法比memcache多得多,作為開發使用到的主要是數據的存取,而其他的事物、通信協議、集群,在一般開發個后臺,不是對速度追求到極致的情況下,還是基本用不到。redis中有按操作分為以下幾種類型:

  1. String:也是key-value對,主要也是對它的鍵對應的元素進行get、set、求長度、自增等操作,redis將添加的類型全存為字符串,即便純數字;

  

  2. Hash:哈希表(散列表),就是數據結構中的字典,采用特定的散列算法,比如手機通訊錄有幾百人,以姓的第一個字母作為關鍵碼進行排序,這樣我們可以快速找到聯系人,這是通過特定的映射方式,將一個字母與姓名聯系起來。在redis中,創建hash表時,首先指定表名,你存在哪張表里邊,然后指定一個域(field,實際就是一個變量),和它對應的值,單用cmd操作就像下面這樣(在hash表hash1中存儲一個域username對應值Jack,redis會自動建立username到Jack的映射),一張hash表里邊可以存儲多個域和對應的變量;

  

  3. List:列表,相當于數據結構的鏈表,通過它還可實現棧和隊列,前面的string(這名字取得很怪異)存儲一一對應的單個鍵值對,它則存多個值(沒有鍵),重點是作為一個列表結構,它可以分別從左右(表頭和表尾)進行插入和彈出變量值,求長度等一系列操作,這也是為什么稱為列表,下面lpush、rpush命令就是從表左邊和右邊插入變量hello和world;

  

  4. Set:集合,顧名思義也可以存儲多個變量值(沒有鍵),只是符合數學上定義的集合的特性,比如集合中元素不重復,因此set中各個數據對的鍵名也不一樣,它也可以進行并、交、差等運算(下面命令是向集合mySet添加一個值var);

  

5. SortedSet:有序集合,可看做Set的特殊方式,在每一個SortedSet類型集合中,添加一個值(沒有鍵)時,都要給它們指定一個稱為score的變量值,有序有序,得有個字段來判定它的順序是不,就是這個玩意兒,下面命令創建一個有序集合stset,添加一個值google.com,它的score是10。其實猜也猜得到,既然叫有序集合,既然給定了score,基本確定可以用這個來進行某些排序操作,事實也是這樣;

  

  6. Key:單獨對鍵進行操作,當然對其對應的元素值也有影響,如查看鍵對應元素的數據類型、鍵對應元素的存活時間、重置存活時間、返回所有鍵、正則形式查看相關鍵名、刪除鍵(元素也跟著沒了)等等。它不是數據類型,實際上,Redis把Hash表表名、List列表表名、集合Set名都稱為鍵,整個集合或者表是它的值。下面是type命令查看它存儲值得類型,它存儲的是List列表。

  

  上面這些命令,找個參考文檔走一遍,很快就能玩熟,個人在這兒也只是泛泛而談。那么在實際項目中,通常是怎樣使用緩存呢?不往大的談,比如微博的緩存設計,這可能涉及到架構層面的東西了,單說作為一個有一定訪問量的后臺,又想使用緩存來提高速度的情況下。

  一個重要的原則(個人目前碰得多的情況)是,以傳入的參數來拼鍵名,以這個鍵名來存取值。比如現在Model模型類里面有個方法:getUserInfoByUid($params),傳入包含uid字段的數組查詢這個用戶的信息,在這兒使用緩存,先取緩存數據,取不到則去查數據庫,然后重新加入緩存,最后返回結果數據,這也是使用緩存的一個通用流程。

  以Memcache為例,先看代碼,定義一個Cache類:

    /**     * Memcache緩存類     */    define('CACHE_HOST', '127.0.0.1');    define('CACHE_PORT', 11211);        class Cache{        PRivate static $instance = null;                  private $_cache = null;  // 緩存操作對象                const prefix = 'APP|';  // 緩存鍵值的前綴,為該項目名稱                 private function __construct(){            if($this->_cache === null){                try{                    $this->_cache = new Memcache;                    if(!$this->_cache->connect(CACHE_HOST, CACHE_PORT)){                        exit('connect failed');                    }                                    }                catch(Exception $e){                    echo 'ERROR: '.$e->getMessage();                }                            }        }        /**          * 返回單例         */        public static function getInstance(){            if(self::$instance === null){                self::$instance = new self();            }            return self::$instance;        }        /**         * 生成鍵名         */        private function genKey($key){            return Cache::prefix.$key;        }                public function __destruct(){            if($this->_cache !== null){                return $this->_cache->close();            }        }        /**         * 添加元素,設置過期時間         */        public function add($key, $val, $expire = 3600){            return $this->_cache->add($this->genKey($key), $val, 0, $expire);        }        /**         * 重置元素         */        public function set($key, $val, $expire = 3600){            echo 'cache key: '.$this->genKey($key).'<br/>';  // test            return $this->_cache->set($this->genKey($key), $val, 0, $expire);        }        /**         * 獲取元素         */        public function get($key){            return $this->_cache->get($this->genKey($key));        }        /**         * 自增         */        public function increment($key, $val = 1){            return $this->_cache->increment($this->genKey($key), $val);        }        /**         * 自減         */        public function decrement($key, $val = 1){            return $this->_cache->decrement($this->genKey($key), $val);        }        /**         * 刪除元素         */        public function delete($key, $timeout = 0){            return $this->_cache->delete($this->genKey($key), $timeout);        }        /**         * 刪除所有元素         */        public function flush(){            return $this->_cache->flush();        }        }

  然后定義一個操作數據庫操作類:

    /**     * 數據庫操作     */    define('DB_NAME', 'test');    define('DB_HOST', '127.0.0.1');    define('DB_PORT', 3306);    define('DB_USER', 'root');    define('DB_PASS', '1234');        class Dal{        private static $instance = null;                public $pdo = null;                        private function __construct(){            try{                $dsn = 'MySQL:dbname='.DB_NAME.';host='.DB_HOST.':'.DB_PORT;                $this->pdo = new PDO($dsn, DB_USER, DB_PASS);            }            catch(PDOException $e){                echo 'Error: '.$e->getMessage();                return false;            }        }        //獲取實例        public static function getInstance(){            if(self::$instance === null){                self::$instance = new self();            }            return self::$instance;        }        // 獲取用戶信息        public function getUserInfoByUid($uid){            $sql = sprintf('select * from tab1 where uid = %s limit 1', $ui
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 白水县| 鹤峰县| 华蓥市| 全椒县| 烟台市| 崇文区| 乡城县| 嘉义市| 电白县| 岑溪市| 普定县| 汨罗市| 河北区| 黔南| 额济纳旗| 革吉县| 海林市| 巴塘县| 青神县| 尖扎县| 海丰县| 拜泉县| 克山县| 清原| 会泽县| 寿光市| 湾仔区| 重庆市| 潍坊市| 桂林市| 奉贤区| 涟源市| 丁青县| 卢湾区| 霍林郭勒市| 绥中县| 峨眉山市| 台州市| 金平| 昭通市| 陇川县|