什麼是 Yac
從名字其實就能看出,這又是鳥哥大神的作品。畢竟是 PHP 的核心開發人員,他的作品每次都不會讓我們失望。鳥哥可以說是我們中國程式設計師的驕傲,他在 PHP 界有舉足輕重的地位,大家可以自己搜尋一下他的博客,雖說更新頻率不高,但每篇文章都值得我們學習。
Yac 是一個無鎖共享快取系統,因為無鎖,所以它的效率非常高。據說 Apc 的效率是 Memcached 的一倍以上,而 Yac 比 Apc 更快。這就是它最大的特色。
相對於 Memcached 或 Redis 來說,Yac 更加輕量級,我們也不需要在伺服器中再安裝別的什麼軟體,只需要安裝這個擴充功能就可以使用。對於小型系統特別是就是簡單的進行資料快取的系統來說,我們不需要複雜的資料類型,只用這種程式語言的擴充就能讓我們的開發更為方便快速。
安裝的方式也非常簡單,一樣的在 PECL 下載安裝套件後進行擴充安裝即可。
基本操作
對於快取相關的操作,無外乎就是新增、修改、刪除快取。不像外部快取系統,在保存陣列或物件時,PHP 擴充類別的快取都能直接保存這些資料類型,而不會序列化為字串或轉換為 JSON 字串,這是 Apc 和 Yac 的優勢之一。
新增、取得快取
$yac = new Yac(); $yac->add('a', 'value a'); $yac->add('b', [1,2,3,4]); $obj = new stdClass; $obj->v = 'obj v'; $yac->add('obj', $obj); echo $yac->get('a'), PHP_EOL; // value a echo $yac->a, PHP_EOL; // value a print_r($yac->get('b')); // Array // ( // [0] => 1 // [1] => 2 // [2] => 3 // [3] => 4 // ) var_dump($yac->get('obj')); // object(stdClass)#3 (1) { // ["v"]=> // string(5) "obj v" // }
非常簡單的操作,我們只需要實例化一個 Yac 類,就可以透過 add() 方法及 get() 方法新增和取得快取內容。
Yac 擴充功能也重寫了 __set() 和 __get() 魔術方法,所以我們可以直接透過操作變數的方式來操作快取。
接下來,我們可以透過 info() 函數查看目前快取的狀態資訊。
print_r($yac->info()); // Array // ( // [memory_size] => 71303168 // [slots_memory_size] => 4194304 // [values_memory_size] => 67108864 // [segment_size] => 4194304 // [segment_num] => 16 // [miss] => 0 // [hits] => 4 // [fails] => 0 // [kicks] => 0 // [recycles] => 0 // [slots_size] => 32768 // [slots_used] => 3 // )
設定快取
$yac->set('a', 'new value a!'); echo $yac->a, PHP_EOL; // new value a! $yac->a = 'best new value a!'; echo $yac->a, PHP_EOL; // best new value a!
set() 函數的作用就是如果目前快取 key 存在,就修改這個快取的內容,如果不存在,就建立一個快取。
刪除快取
$yac->delete('a'); echo $yac->a, PHP_EOL; // $yac->flush(); print_r($yac->info()); // Array // ( // [memory_size] => 71303168 // [slots_memory_size] => 4194304 // [values_memory_size] => 67108864 // [segment_size] => 4194304 // [segment_num] => 16 // [miss] => 1 // [hits] => 6 // [fails] => 0 // [kicks] => 0 // [recycles] => 0 // [slots_size] => 32768 // [slots_used] => 0 // )
對於單一快取的刪除,我們可以直接使用 delete() 函數來刪除這個快取的內容。如果要清空整個快取空間,就可以直接使用 flush() 來清空整個快取空間。
別名空間
上面我們提到了 快取空間 這個東西。其實也就是在實例化 Yac 的時候可以給預設的 Yac 類別建構子傳遞一個別名配置。這樣,不同的 Yac 實例就等於放在了不同的命名空間中,相同的 Key 的快取在不同的空間中就不會相互影響。
$yacFirst = new Yac(); $yacFirst->a = 'first a!';; $yacSecond = new Yac(); $yacSecond->a = 'second a!'; echo $yacFirst->a, PHP_EOL; // second a! echo $yacSecond->a, PHP_EOL; // second a!
這段程式碼我們都是使用的預設的實例化 Yac 對象,雖說是分開實例化的,但它們保存的空間是一樣的,所以相同的 a 變數會相互覆蓋。
$yacFirst = new Yac('first'); $yacFirst->a = 'first a!';; $yacSecond = new Yac('second'); $yacSecond->a = 'second a!'; echo $yacFirst->a, PHP_EOL; // first a! echo $yacSecond->a, PHP_EOL; // second a!
當我們使用不同的實例化參數之後,相同的 a 就不會相互影響,它們被儲存在了不同的空間中。或者說,Yac 會自動為這些 Key 增加一個 prefix 。
快取時效
最後,快取系統都會針對快取內容有時效限制,如果指定了過期時間,快取內容就會在指定的時間之後過期。
$yac->add('ttl', '10s', 10); $yac->set('ttl2', '20s', 20); echo $yac->get('ttl'), PHP_EOL; // 10s echo $yac->ttl2, PHP_EOL; // 20s sleep(10); echo $yac->get('ttl'), PHP_EOL; // echo $yac->ttl2, PHP_EOL; // 20s
上述程式碼中的 ttl 快取只設定了 10 秒的過期時間,所以在 sleep() 10 秒後,輸出 ttl 就沒有任何內容了。
要注意的是,對於時間的設置,如果不設定的話就是長久有效,而且不能用__set() 方法設定過期時間,只能使用set() 或add() 函數來設定過期時間。
總結
怎麼樣,Yac 擴充功能是不是跟我們的 Apc 一樣方便好用,當然,更主要的是它的效能以及適用場景。對於小型系統,特別是機器配置不是那麼強的操作環境中,這種擴充型的快取系統能夠讓我們的開發更加的快速方便。關於無鎖共享的概念我們可以參考下方參考文檔中第二個鏈接,也就是鳥哥的文章中有詳細的說明。
測試程式碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202006/source/PHP%E7%9A%84%E5%8F%A6%E4%B8%80%E4%B8%AA%E9%AB%98%E6%95%88%E7%BC%93%E5%AD%98%E6%89%A9%E5%B1%95%EF%BC%9AYac.php
推薦學習:php影片教學