キャッシュによるパフォーマンス改善 ================================== Phalcon provides the :doc:`Phalcon\\Cache ` class allowing faster access to frequently used or already processed data. :doc:`Phalcon\\Cache ` is written in C, achieving higher performance and reducing the overhead when getting items from the backends. This class uses an internal structure of frontend and backend components. Front-end components act as input sources or interfaces, while backend components offer storage options to the class. どのような時にキャッシュを実装する? ------------------------------------ Although this component is very fast, implementing it in cases that are not needed could lead to a loss of performance rather than gain. We recommend you check this cases before using a cache: * You are making complex calculations that every time return the same result (changing infrequently) * You are using a lot of helpers and the output generated is almost always the same * You are accessing database data constantly and these data rarely change .. highlights:: *NOTE* Even after implementing the cache, you should check the hit ratio of your cache over a period of time. This can easily be done, especially in the case of Memcache or Apc, with the relevant tools that the backends provide. キャッシュの振る舞い -------------------- The caching process is divided into 2 parts: * **Frontend**: This part is responsible for checking if a key has expired and perform additional transformations to the data before storing and after retrieving them from the backend- * **Backend**: This part is responsible for communicating, writing/reading the data required by the frontend. 出力する部品のキャッシュ ------------------------ An output fragment is a piece of HTML or text that is cached as is and returned as is. The output is automatically captured from the ob_* functions or the PHP output so that it can be saved in the cache. The following example demonstrates such usage. It receives the output generated by PHP and stores it into a file. The contents of the file are refreshed every 172800 seconds (2 days). The implementation of this caching mechanism allows us to gain performance by not executing the helper :code:`Phalcon\Tag::linkTo()` call whenever this piece of code is called. .. code-block:: php 172800, ] ); // Create the component that will cache from the "Output" to a "File" backend // Set the cache file directory - it's important to keep the "/" at the end of // the value for the folder $cache = new BackFile( $frontCache, [ "cacheDir" => "../app/cache/", ] ); // Get/Set the cache file to ../app/cache/my-cache.html $content = $cache->start("my-cache.html"); // If $content is null then the content will be generated for the cache if ($content === null) { // Print date and time echo date("r"); // Generate a link to the sign-up action echo Tag::linkTo( [ "user/signup", "Sign Up", "class" => "signup-button", ] ); // Store the output into the cache file $cache->save(); } else { // Echo the cached output echo $content; } *NOTE* In the example above, our code remains the same, echoing output to the user as it has been doing before. Our cache component transparently captures that output and stores it in the cache file (when the cache is generated) or it sends it back to the user pre-compiled from a previous call, thus avoiding expensive operations. 任意のデータのキャッシュ ------------------------ Caching just data is equally important for your application. Caching can reduce database load by reusing commonly used (but not updated) data, thus speeding up your application. ファイルをバックエンドとする例 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ One of the caching adapters is 'File'. The only key area for this adapter is the location of where the cache files will be stored. This is controlled by the cacheDir option which *must* have a backslash at the end of it. .. code-block:: php 172800, ] ); // Create the component that will cache "Data" to a "File" backend // Set the cache file directory - important to keep the "/" at the end of // the value for the folder $cache = new BackFile( $frontCache, [ "cacheDir" => "../app/cache/", ] ); $cacheKey = "robots_order_id.cache"; // Try to get cached records $robots = $cache->get($cacheKey); if ($robots === null) { // $robots is null because of cache expiration or data does not exist // Make the database call and populate the variable $robots = Robots::find( [ "order" => "id", ] ); // Store it in the cache $cache->save($cacheKey, $robots); } // Use $robots :) foreach ($robots as $robot) { echo $robot->name, "\n"; } Memcached をバックエンドとする例 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The above example changes slightly (especially in terms of configuration) when we are using a Memcached backend. .. code-block:: php 3600, ] ); // Create the component that will cache "Data" to a "Memcached" backend // Memcached connection settings $cache = new BackMemCached( $frontCache, [ "servers" => [ [ "host" => "127.0.0.1", "port" => "11211", "weight" => "1", ] ] ] ); $cacheKey = "robots_order_id.cache"; // Try to get cached records $robots = $cache->get($cacheKey); if ($robots === null) { // $robots is null because of cache expiration or data does not exist // Make the database call and populate the variable $robots = Robots::find( [ "order" => "id", ] ); // Store it in the cache $cache->save($cacheKey, $robots); } // Use $robots :) foreach ($robots as $robot) { echo $robot->name, "\n"; } キャッシュの参照 ------------------ The elements added to the cache are uniquely identified by a key. In the case of the File backend, the key is the actual filename. To retrieve data from the cache, we just have to call it using the unique key. If the key does not exist, the get method will return null. .. code-block:: php get("myProducts"); If you want to know which keys are stored in the cache you could call the queryKeys method: .. code-block:: php queryKeys(); foreach ($keys as $key) { $data = $cache->get($key); echo "Key=", $key, " Data=", $data; } // Query keys in the cache that begins with "my-prefix" $keys = $cache->queryKeys("my-prefix"); Deleting data from the cache ---------------------------- There are times where you will need to forcibly invalidate a cache entry (due to an update in the cached data). The only requirement is to know the key that the data have been stored with. .. code-block:: php delete("someKey"); $keys = $cache->queryKeys(); // Delete all items from the cache foreach ($keys as $key) { $cache->delete($key); } キャッシュが存在するかの確認 ---------------------------- It is possible to check if a cache already exists with a given key: .. code-block:: php exists("someKey")) { echo $cache->get("someKey"); } else { echo "Cache does not exists!"; } 保存期間 -------- A "lifetime" is a time in seconds that a cache could live without expire. By default, all the created caches use the lifetime set in the frontend creation. You can set a specific lifetime in the creation or retrieving of the data from the cache: Setting the lifetime when retrieving: .. code-block:: php get($cacheKey, 3600); if ($robots === null) { $robots = "some robots"; // Store it in the cache $cache->save($cacheKey, $robots); } Setting the lifetime when saving: .. code-block:: php get($cacheKey); if ($robots === null) { $robots = "some robots"; // Setting the cache when saving data $cache->save($cacheKey, $robots, 3600); } マルチレベル・キャッシュ ------------------------ This feature of the cache component, allows the developer to implement a multi-level cache. This new feature is very useful because you can save the same data in several cache locations with different lifetimes, reading first from the one with the faster adapter and ending with the slowest one until the data expires: .. code-block:: php 3600, ] ); $fastFrontend = new DataFrontend( [ "lifetime" => 86400, ] ); $slowFrontend = new DataFrontend( [ "lifetime" => 604800, ] ); // Backends are registered from the fastest to the slower $cache = new Multiple( [ new ApcCache( $ultraFastFrontend, [ "prefix" => "cache", ] ), new MemcacheCache( $fastFrontend, [ "prefix" => "cache", "host" => "localhost", "port" => "11211", ] ), new FileCache( $slowFrontend, [ "prefix" => "cache", "cacheDir" => "../app/cache/", ] ), ] ); // Save, saves in every backend $cache->save("my-key", $data); フロントエンド・アダプタ ------------------------- The available frontend adapters that are used as interfaces or input sources to the cache are: +------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Adapter | Description | +====================================================================================+================================================================================================================================================================+ | :doc:`Phalcon\\Cache\\Frontend\\Output <../api/Phalcon_Cache_Frontend_Output>` | Read input data from standard PHP output | +------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :doc:`Phalcon\\Cache\\Frontend\\Data <../api/Phalcon_Cache_Frontend_Data>` | It's used to cache any kind of PHP data (big arrays, objects, text, etc). Data is serialized before stored in the backend. | +------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :doc:`Phalcon\\Cache\\Frontend\\Base64 <../api/Phalcon_Cache_Frontend_Base64>` | It's used to cache binary data. The data is serialized using base64_encode before be stored in the backend. | +------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :doc:`Phalcon\\Cache\\Frontend\\Json <../api/Phalcon_Cache_Frontend_Json>` | Data is encoded in JSON before be stored in the backend. Decoded after be retrieved. This frontend is useful to share data with other languages or frameworks. | +------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :doc:`Phalcon\\Cache\\Frontend\\Igbinary <../api/Phalcon_Cache_Frontend_Igbinary>` | It's used to cache any kind of PHP data (big arrays, objects, text, etc). Data is serialized using IgBinary before be stored in the backend. | +------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :doc:`Phalcon\\Cache\\Frontend\\None <../api/Phalcon_Cache_Frontend_None>` | It's used to cache any kind of PHP data without serializing them. | +------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ Implementing your own Frontend adapters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The :doc:`Phalcon\\Cache\\FrontendInterface <../api/Phalcon_Cache_FrontendInterface>` interface must be implemented in order to create your own frontend adapters or extend the existing ones. Backend Adapters ---------------- The backend adapters available to store cache data are: +----------------------------------------------------------------------------------+------------------------------------------------+------------+---------------------+ | Adapter | Description | Info | Required Extensions | +==================================================================================+================================================+============+=====================+ | :doc:`Phalcon\\Cache\\Backend\\File <../api/Phalcon_Cache_Backend_File>` | Stores data to local plain files | | | +----------------------------------------------------------------------------------+------------------------------------------------+------------+---------------------+ | :doc:`Phalcon\\Cache\\Backend\\Memcache <../api/Phalcon_Cache_Backend_Memcache>` | Stores data to a memcached server | Memcached_ | memcache_ | +----------------------------------------------------------------------------------+------------------------------------------------+------------+---------------------+ | :doc:`Phalcon\\Cache\\Backend\\Apc <../api/Phalcon_Cache_Backend_Apc>` | Stores data to the Alternative PHP Cache (APC) | APC_ | `APC extension`_ | +----------------------------------------------------------------------------------+------------------------------------------------+------------+---------------------+ | :doc:`Phalcon\\Cache\\Backend\\Mongo <../api/Phalcon_Cache_Backend_Mongo>` | Stores data to Mongo Database | MongoDb_ | `Mongo`_ | +----------------------------------------------------------------------------------+------------------------------------------------+------------+---------------------+ | :doc:`Phalcon\\Cache\\Backend\\Xcache <../api/Phalcon_Cache_Backend_Xcache>` | Stores data in XCache | XCache_ | `xcache extension`_ | +----------------------------------------------------------------------------------+------------------------------------------------+------------+---------------------+ | :doc:`Phalcon\\Cache\\Backend\\Redis <../api/Phalcon_Cache_Backend_Redis>` | Stores data in Redis | Redis_ | `redis extension`_ | +----------------------------------------------------------------------------------+------------------------------------------------+------------+---------------------+ Implementing your own Backend adapters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The :doc:`Phalcon\\Cache\\BackendInterface <../api/Phalcon_Cache_BackendInterface>` interface must be implemented in order to create your own backend adapters or extend the existing ones. ファイル・バックエンド オプション ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This backend will store cached content into files in the local server. The available options for this backend are: +----------+-------------------------------------------------------------+ | Option | Description | +==========+=============================================================+ | prefix | A prefix that is automatically prepended to the cache keys | +----------+-------------------------------------------------------------+ | cacheDir | A writable directory on which cached files will be placed | +----------+-------------------------------------------------------------+ Memcached バックエンド オプション ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This backend will store cached content on a memcached server. The available options for this backend are: +------------+-------------------------------------------------------------+ | Option | Description | +============+=============================================================+ | prefix | A prefix that is automatically prepended to the cache keys | +------------+-------------------------------------------------------------+ | host | memcached host | +------------+-------------------------------------------------------------+ | port | memcached port | +------------+-------------------------------------------------------------+ | persistent | create a persistent connection to memcached? | +------------+-------------------------------------------------------------+ APC バックエンド オプション ^^^^^^^^^^^^^^^^^^^^^^^^^^^ This backend will store cached content on Alternative PHP Cache (APC_). The available options for this backend are: +------------+-------------------------------------------------------------+ | Option | Description | +============+=============================================================+ | prefix | A prefix that is automatically prepended to the cache keys | +------------+-------------------------------------------------------------+ Mongo バックエンド オプション ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This backend will store cached content on a MongoDB server. The available options for this backend are: +------------+-------------------------------------------------------------+ | Option | Description | +============+=============================================================+ | prefix | A prefix that is automatically prepended to the cache keys | +------------+-------------------------------------------------------------+ | server | A MongoDB connection string | +------------+-------------------------------------------------------------+ | db | Mongo database name | +------------+-------------------------------------------------------------+ | collection | Mongo collection in the database | +------------+-------------------------------------------------------------+ XCache バックエンド オプション ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This backend will store cached content on XCache (XCache_). The available options for this backend are: +------------+-------------------------------------------------------------+ | Option | Description | +============+=============================================================+ | prefix | A prefix that is automatically prepended to the cache keys | +------------+-------------------------------------------------------------+ Redis Backend Options ^^^^^^^^^^^^^^^^^^^^^ This backend will store cached content on a Redis server (Redis_). The available options for this backend are: +------------+---------------------------------------------------------------+ | Option | Description | +============+===============================================================+ | prefix | A prefix that is automatically prepended to the cache keys | +------------+---------------------------------------------------------------+ | host | Redis host | +------------+---------------------------------------------------------------+ | port | Redis port | +------------+---------------------------------------------------------------+ | auth | Password to authenticate to a password-protected Redis server | +------------+---------------------------------------------------------------+ | persistent | Create a persistent connection to Redis | +------------+---------------------------------------------------------------+ | index | The index of the Redis database to use | +------------+---------------------------------------------------------------+ There are more adapters available for this components in the `Phalcon Incubator `_ .. _Memcached: http://www.php.net/memcache .. _memcache: http://pecl.php.net/package/memcache .. _APC: http://php.net/apc .. _APC extension: http://pecl.php.net/package/APC .. _MongoDb: http://mongodb.org/ .. _Mongo: http://pecl.php.net/package/mongo .. _XCache: http://xcache.lighttpd.net/ .. _XCache extension: http://pecl.php.net/package/xcache .. _Redis: http://redis.io/ .. _redis extension: http://pecl.php.net/package/redis