成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

PHP+Redis緩存技術(shù)一覽

開發(fā)
加入緩存技術(shù)之后,原來方法的 調(diào)用方式和返回的數(shù)據(jù)結(jié)構(gòu) 都不應該改變。

有否想過PHP使用 redis 作為緩存時,如何能:

1.前后臺模塊共用Model層;

2. 但是,不能每個Model類都進行緩存,這樣太浪費Redis資源;

3. 前后臺模塊可以自由決定從數(shù)據(jù)庫還是從緩存讀數(shù)據(jù);

4. 沒有冗余代碼;

5. 使用方便。

這里我們先展示實現(xiàn)的最終效果。

最終的代碼和使用說明請移步Github:

https://github.com/yeszao/php-redis-cache

馬上安裝使用命令:

$ composer install yeszao/cache

經(jīng)過簡單配置就可以使用,請參看Github的README說明。

1、最終效果

假設(shè)在MVC框架中, model 層有一個 Book 類和一個 getById 方法,如下:

class Book

{
public function getById($id)
{
return $id;
}
}

加入緩存技術(shù)之后,原來方法的 調(diào)用方式 和 返回的數(shù)據(jù)結(jié)構(gòu) 都不應該改變。

所以,我們希望,最后的效果應該是這樣的:

(new Book)->getById(100);           // 原始的、不用緩存的調(diào)用方式,還是原來的方式,一般是讀取數(shù)據(jù)庫的數(shù)據(jù)
(new Book)->getByIdCache(100); // 使用緩存的調(diào)用方式,緩存鍵名為:app_models_book:getbyid: + md5(參數(shù)列表)
(new Book)->getByIdClear(100); // 刪除這個緩存
(new Book)->getByIdFlush(); // 刪除 getById() 方法對應的所有緩存,即刪除 app_models_book:getbyid:*。這個方法不需要參數(shù)。

這樣我們可以很清楚的明白自己在做什么,同時又知道數(shù)據(jù)的來源函數(shù),并且被引用方式完全統(tǒng)一,可謂一箭三雕。

其實實現(xiàn)起來也比較簡單,就是使用PHP的魔術(shù)方法 __call() 方法。

2、__call()方法

這里簡單說明一下 __call 方法的作用。

在PHP中,當我們訪問一個不存在的類方法時,就會調(diào)用這個類的 __call() 方法。

(如果類方法不存在,又沒有寫 __call() 方法,PHP會直接報錯)

假設(shè)我們有一個 Book 類:

class Book
{
public function __call($name, $arguments)
{
echo '類Book不存在方法', $name, PHP_EOL;
}

public function getById($id)
{
echo '我的ID是', $id, PHP_EOL;
}
}

當調(diào)用 存在的 getName(50) 方法時,程序打印: 我的ID是50 。

而如果調(diào)用 不存在的 getAge() 方法時,程序就會執(zhí)行到A類的 __call() 方法里面,這里會打印: 類Book不存在方法getAge 。

這就是 __call 的原理。

3、實現(xiàn)細節(jié)

接下來我們就利用 __call() 方法的這種特性,來實現(xiàn)緩存策略。

從上面的例子,我們看到, __call() 方法被調(diào)用時,會傳入兩個參數(shù)。

$name :想要調(diào)用的方法名

$arguments :參數(shù)列表

我們就可以在參數(shù)上面做文章。

還是以 Book 類為例,我們假設(shè)其原本結(jié)構(gòu)如下:

class Book
{
public function __call($name, $arguments)
{
// 待填充內(nèi)容
}
public function getById($id)
{
return ['id' => $id, 'title' => 'PHP緩存技術(shù)' . $id];
}
}

開始之前,我們還確認Redis的連接,這是緩存必須用到的,這里我們寫個簡單的單例類:

class Common
{
private static $redis = null;

public static function redis()
{
if (self::$redis === null) {
self::$redis = new \Redis('127.0.0.1');
self::$redis->connect('redis');
}
return self::$redis;
}

然后,我們開始填充 __call() 方法代碼,具體說明請看注釋:

class Book
{
public function __call($name, $arguments)
{
// 因為我們主要是根據(jù)方法名的后綴決定具體操作,
// 所以如果傳入的 $name 長度小于5,可以直接報錯
if (strlen($name) < 5) {
exit('Method does not exist.');
}
// 接著,我們截取 $name,獲取原方法和要執(zhí)行的動作,
// 是cache、clear還是flush,這里我們?nèi)×藗€巧,動作

// 的名稱都是5個字符,這樣截取就非常高效。
$method = substr($name, 0, -5);
$action = substr($name, -5);
// 當前調(diào)用的類名稱,包括命名空間的名稱
$class = get_class();

// 生成緩存鍵名,$arguments稍后再加上
$key = sprintf('%s:%s:', str_replace('\\', '_', $class), $method);
// 都用小寫好看點
$key = strtolower($key);

switch ($action) {
case 'Cache':
// 緩存鍵名加上$arguments
$key = $key . md5(json_encode($arguments));
// 從Redis中讀取數(shù)據(jù)
$data = Common::redis()->get($key);
// 如果Redis中有數(shù)據(jù)

if ($data !== false) {
$decodeData = json_decode($data, JSON_UNESCAPED_UNICODE);
// 如果不是JSON格式的數(shù)據(jù),直接返回,否則返回json解析后的數(shù)據(jù)
return $decodeData === null ? $data : $decodeData;
}

// 如果Redis中沒有數(shù)據(jù)則繼續(xù)往下執(zhí)行
// 如果原方法不存在
if (method_exists($this, $method) === false) {
exit('Method does not exist.');
}

// 調(diào)用原方法獲取數(shù)據(jù)
$data = call_user_func_array([$this, $method], $arguments);

// 保存數(shù)據(jù)到Redis中以便下次使用
Common::redis()->set($key, json_encode($data), 3600);

// 結(jié)束執(zhí)行并返回數(shù)據(jù)
return $data;
break;

case 'Clear':
// 緩存鍵名加上$arguments
$key = $key . md5(json_encode($arguments));
return Common::redis()->del($key);
break;
case 'Flush':
$key = $key . '*';

// 獲取所有符合 $class:$method:* 規(guī)則的緩存鍵名
$keys = Common::redis()->keys($key);
return Common::redis()->del($keys);
break;
default:
exit('Method does not exist.');
}
}

// 其他方法
}

這樣就實現(xiàn)了我們開始時的效果。

4、實際使用時

在實際使用中,我們需要做一些改變,把這一段代碼歸入一個類中,

然后在model層的基類中引用這個類,再傳入Redis句柄、類對象、方法名和參數(shù),

這樣可以降低代碼的耦合,使用起來也更靈活。

責任編輯:張燕妮 來源: PHP開源社區(qū)
相關(guān)推薦

2009-12-08 13:54:31

PHP時間戳函數(shù)

2009-12-09 13:47:49

PHP Zend框架模

2009-07-07 10:10:05

PHP開源建站程序

2009-07-06 00:29:01

開源PHP

2009-12-08 17:01:01

PHP PEAR DB

2009-08-17 17:19:00

ASP.NET緩存數(shù)據(jù)

2021-04-07 10:13:51

人工智能深度學習

2012-02-27 16:44:01

redisNoSQL

2010-11-15 09:55:35

Oracle轉(zhuǎn)換函數(shù)

2011-01-11 09:53:28

linux進程

2011-01-11 10:06:14

linux進程

2021-06-08 09:47:44

Java面向對象

2023-11-08 07:45:47

Spring微服務(wù)

2019-04-26 14:21:34

手機色彩蘋果

2010-10-14 16:55:00

MySQL聯(lián)結(jié)查詢

2017-03-06 16:34:12

虛擬個人助理

2009-03-03 20:44:06

桌面虛擬化Xendesktop虛擬化

2020-02-17 15:29:00

石墨文檔

2016-01-07 13:19:21

大數(shù)據(jù)分析生態(tài)圈

2009-07-09 17:40:26

Java運算符
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 久久久久久久香蕉 | 久久久久网站 | 国产精品大片 | 无码日韩精品一区二区免费 | 亚洲黄色av网站 | 欧美精品在线播放 | 91精品国产99 | 日韩性在线| 欧美一区二区三区在线看 | 中国一级特黄真人毛片免费观看 | 操一草| 日日干天天干 | 成人免费视频久久 | 超碰av免费| 激情在线视频 | 日韩高清成人 | 成人免费视频 | 亚洲 日本 欧美 中文幕 | 精品永久 | a视频在线观看 | 亚洲精品久久嫩草网站秘色 | 国产做a爱片久久毛片 | 日韩精品久久久久久 | 91久久精品 | 成人h视频在线 | 亚洲一区二区视频在线播放 | 蜜桃毛片| 欧美精品在线一区二区三区 | 久久国产视频网 | 久久国产电影 | 欧美三级在线 | 久久久久久国产免费视网址 | 亚洲国内精品 | 国产视频1区2区 | 亚洲日本欧美日韩高观看 | 中文字幕在线观 | 亚洲一区二区久久 | 蜜桃一区二区三区在线 | 91国内精精品久久久久久婷婷 | 精品乱码一区二区三四区 | 欧美日韩一二三区 |