《深入探究 php-apcu 實現原理》-- 第一回:apcu的簡介、優缺點及使用場景


 

在業務開發的某些場景中使用了apcu進行整體的性能優化,也取得了不錯的效果,所以前兩年就一直想寫寫相關的主題

市面上寫redis的文章或者書籍鋪天蓋地,但是去談apcu的卻沒有多少,有一些也是科普性的如何安裝和使用,所以老趙這里總結一下自己所得,做個分享。

 

我這篇文章的主要結構大概是這樣的:

1.apcu在緩存中地位及使用場景,與redis、mysql或者其他的一些nosql數據庫如何搭配使用

2.apcu的源代碼在哪里,主要涉及哪些技術點

 

 1.APCU是什么?在什么樣的場景使用?

官方對於apc的解釋如下,可選的php緩存技術。apc包含兩個方面,一方面對於本身代碼級別的緩存,另一方面是提供給編碼者使用的類似於redis的set、get這樣的接口。在php 某個版本之后,apcu所提供的用戶緩存部分被保存下來了

The Alternative PHP Cache (APC) is a free and open opcode cache for PHP. Its goal is to provide a free, open, and robust framework for caching and optimizing PHP intermediate code

apcu擴展使用的方法是這樣的:

<?php
$bar = 'BAR';
apcu_add('foo', $bar);
var_dump(apcu_fetch('foo'));
echo "\n";
$bar = 'NEVER GETS SET';
apcu_add('foo', $bar);
var_dump(apcu_fetch('foo'));
echo "\n";
?>

大體上來說,使用的api側與memcahe、redis或者其他的基於磁盤的nosql使用的方式似乎沒什么差別,我畫了一個典型的web架構的示意圖,來標識出來他們各自之間的區別

 

一般現在的架構模式下,負載均衡機器、服務集群、redis集群、mysql集群式相互獨立運維的,也就是我所畫出來的clusterA、clusterB、clusterC、clusterD,按照現在比較流行微服務划分(我對微服務的概念不是很熟),服務間使用網絡協議調用

apcu是基於共享內存技術建設的,多個cgi之間訪問apcu中的cache可以完全等同於訪問自己進程的一塊內存一樣,不需要發任何的網絡請求。

而不管是redis、mysql或者其他的獨立服務的cache都需要發網絡請求,即使存儲和服務部署在同一機器上也仍然需要采用本地sock進行網絡請求,何況在虛擬化的趨勢下,這些存儲服務一定是獨立運行的。

按照計算機存儲器層次結構的理論,訪問內存的速度大概在納秒級別 ,網絡請求的速度在毫秒級別,同機架或者同機房的機器可能在1/10ms左右,還不考慮服務穩定性的情況下。

簡單的進行存取測試,速度至少在千倍以上提升,但是apc在實際的使用中還是存在一定的局限性:

  1. 以擴展的方式接入,跟php這門語言有很強的耦合,而redis作為獨立服務存在,使用協議接入
  2. apcu受限於單機內存的限制,擴展受阻,而目前的redis集群模式已經可以做到動態擴容,理論上無容量風險
  3. apcu數據存於單機內存,多機器之間的數據無法共享,這是他使用場景有限的最大阻礙

所以,我再使用場景中一般用apcu來緩存數據量小、但是讀取量大或者瞬間讀取量大的場景。

比如:

1.你是一個開放平台,你需要對客戶請求做鑒權,這個token過來的請求可以訪問哪些path請求。這個場景下,用戶的token及可訪問的path信息持久化在mysql中,變更頻次小,數據量小,但是可能每秒有10W次請求

這個場景就比較適合apc,相比於直接請求mysql/redis的架構,可以給服務省掉10w - N 次/s的網絡消耗,N為容器數目

2.搶購的場景下,假設量比較大,那么可以使用apc來做s級別的緩存元信息,以防止對於存儲服務的瞬間鏈接量過大,導致失敗的情況。

 

幾個關鍵字:數據大小小、讀取量大、配置信息、無狀態

而有狀態的信息你還是選擇mysql/redis,所以這么來看,他的場景的確是有限。但是在有限場景也能發揮他的價值,作為php多進程之間通信的一種方式,也順利幫我優化了幾萬/s的mysql、redis請求。


對於現在的web服務端編程而言,單個api請求帶來的io轉化次數是影響服務性能、穩定性的最大的因素(前提是沒有慢sql),我曾經見到一個api平均轉化了80次mysql,如果請求突增,加機器都很難解決
統一rpc請求的日志,做好access_cps / rpc_cps 指標監控及上線前的准入還是非常重要的,當然兩份日志求交也可以天級別分析出哪些api可能需要優化了

2.APCU源碼及涉及的技術點?

作者深知我們這些phper撲在了創造互聯網價值創造的一線,基礎相對薄弱,面對C代碼可能一頭霧水,特地寫了一篇英文的Readme,詳細的介紹了實現所用到的技術及原理,多貼心

apcu源碼的git地址在: https://github.com/krakjoe/apcu

實現說明文檔在源碼目錄中的 TECHNOTES.txt文件下,當然看懂這系列文章的背后,你是需要補充一下內存方向的一些基本知識的:

  1. php  SAPI是什么?MINIT、RINIT階段做了什么?及擴展開發需要做的一些事情
  2. 關於進程中內存的布局、共享內存技術、虛擬內存與物理內存、內存管理與分配

 

介紹先到這里,暫時給自己立個flag,后面的連載節奏是:

  1. php生命周期及擴展相關知識,具體結合apcu在每個階段做了什么,為后續的技術點展開做好知識預告
  2. 從內存共享,引出mmap、shm等技術點,從而再復習一下進程中內存的布局、虛擬內存與mmap等的關系
  3. 進程間可以共享內存了,如何分配內存? 引 出molloc、free等基於堆的內存分配的實現及與apcu的內存分配器
  4. 內存分配之后,上層的數據結構如何構建能夠做到基於key的數據檢索?過期鍵如何實現

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM