diff --git a/docs/guide-zh-CN/caching-data.md b/docs/guide-zh-CN/caching-data.md new file mode 100644 index 0000000..bf69bce --- /dev/null +++ b/docs/guide-zh-CN/caching-data.md @@ -0,0 +1,284 @@ +数据缓存 +============ + +数据缓存是指将一些 PHP 变量存储到缓存中,使用时再从缓存中取回。 +它也是更高级缓存特性的基础,例如 [查询缓存](#query-caching) 和 [内容缓存](caching-content.md). + +如下代码是一个典型的数据缓存使用模式。其中 `$cache` 代表一个 [缓存组件](#cache-components): + +```php +// 尝试从缓存中取出 $data +$data = $cache->get($key); + +if ($data === false) { + + // $data 在缓存中没有找到,则重新计算它的值 + + // 将 $data 存放到缓存供下次使用 + $cache->set($key, $data); +} + +// 这儿 $data 可以使用了。 +``` + + +## 缓存组件 + +数据缓存需要称作“*缓存组件*”的东西提供支持,它代表着各种缓存存储介质,例如内存,文件,数据库。 + +缓存组件通常注册为应用程序组件,这样它们就可以接受全局性配置和调用。如下代码演示了如何配置 `cache` +应用程序组件使用两个 [memcached](http://memcached.org/) 服务器: + +```php +'components' => [ + 'cache' => [ + 'class' => 'yii\caching\MemCache', + 'servers' => [ + [ + 'host' => 'server1', + 'port' => 11211, + 'weight' => 100, + ], + [ + 'host' => 'server2', + 'port' => 11211, + 'weight' => 50, + ], + ], + ], +], +``` + +然后你就可以通过 `Yii::$app->cache` 访问上面的缓存组件了。 + +由于所有缓存组件都支持同样的一系列 API ,你并不需要修改使用缓存的那些代码就能直接替换为其他低层缓存组件, +只需在应用程序配置中重新配置一下就可以。例如,你可以将上述配置修改为使用 [[yii\caching\ApcCache|APC cache]]: + + +```php +'components' => [ + 'cache' => [ + 'class' => 'yii\caching\ApcCache', + ], +], +``` + +> Tip: 你可以注册多个缓存组件,很多依赖缓存的类默认调用名为 `cache` 的组件(例如 [[yii\web\UrlManager]])。 + + +### Supported Cache Storage + +Yii supports a wide range of cache storage. The following is a summary: + +* [[yii\caching\ApcCache]]: uses PHP [APC](http://php.net/manual/en/book.apc.php) extension. This option can be + considered as the fastest one when dealing with cache for a centralized thick application (e.g. one + server, no dedicated load balancers, etc.). +* [[yii\caching\DbCache]]: uses a database table to store cached data. To use this cache, you must + create a table as specified in [[yii\caching\DbCache::cacheTable]]. +* [[yii\caching\DummyCache]]: serves as a cache placeholder which does no real caching. + The purpose of this component is to simplify the code that needs to check the availability of cache. + For example, during development or if the server doesn't have actual cache support, you may configure + a cache component to use this cache. When an actual cache support is enabled, you can switch to use + the corresponding cache component. In both cases, you may use the same code + `Yii::$app->cache->get($key)` to attempt retrieving data from the cache without worrying that + `Yii::$app->cache` might be `null`. +* [[yii\caching\FileCache]]: uses standard files to store cached data. This is particular suitable + to cache large chunk of data, such as page content. +* [[yii\caching\MemCache]]: uses PHP [memcache](http://php.net/manual/en/book.memcache.php) + and [memcached](http://php.net/manual/en/book.memcached.php) extensions. This option can be considered as + the fastest one when dealing with cache in a distributed applications (e.g. with several servers, load + balancers, etc.) +* [[yii\redis\Cache]]: implements a cache component based on [Redis](http://redis.io/) key-value store + (redis version 2.6.12 or higher is required). +* [[yii\caching\WinCache]]: uses PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) + ([see also](http://php.net/manual/en/book.wincache.php)) extension. +* [[yii\caching\XCache]]: uses PHP [XCache](http://xcache.lighttpd.net/) extension. +* [[yii\caching\ZendDataCache]]: uses + [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) + as the underlying caching medium. + + +> Tip: You may use different cache storage in the same application. A common strategy is to use memory-based + cache storage to store data that is small but constantly used (e.g. statistical data), and use file-based + or database-based cache storage to store data that is big and less frequently used (e.g. page content). + + +## Cache APIs + +All cache components have the same base class [[yii\caching\Cache]] and thus support the following APIs: + +* [[yii\caching\Cache::get()|get()]]: retrieves a data item from cache with a specified key. A false + value will be returned if the data item is not found in the cache or is expired/invalidated. +* [[yii\caching\Cache::set()|set()]]: stores a data item identified by a key in cache. +* [[yii\caching\Cache::add()|add()]]: stores a data item identified by a key in cache if the key is not found in the cache. +* [[yii\caching\Cache::mget()|mget()]]: retrieves multiple data items from cache with the specified keys. +* [[yii\caching\Cache::mset()|mset()]]: stores multiple data items in cache. Each item is identified by a key. +* [[yii\caching\Cache::madd()|madd()]]: stores multiple data items in cache. Each item is identified by a key. + If a key already exists in the cache, the data item will be skipped. +* [[yii\caching\Cache::exists()|exists()]]: returns a value indicating whether the specified key is found in the cache. +* [[yii\caching\Cache::delete()|delete()]]: removes a data item identified by a key from the cache. +* [[yii\caching\Cache::flush()|flush()]]: removes all data items from the cache. + +Some cache storage, such as MemCache, APC, support retrieving multiple cached values in a batch mode, +which may reduce the overhead involved in retrieving cached data. The APIs [[yii\caching\Cache::mget()|mget()]] +and [[yii\caching\Cache::madd()|madd()]] are provided to exploit this feature. In case the underlying cache storage +does not support this feature, it will be simulated. + +Because [[yii\caching\Cache]] implements `ArrayAccess`, a cache component can be used liked an array. The followings +are some examples: + +```php +$cache['var1'] = $value1; // equivalent to: $cache->set('var1', $value1); +$value2 = $cache['var2']; // equivalent to: $value2 = $cache->get('var2'); +``` + + +### Cache Keys + +Each data item stored in cache is uniquely identified by a key. When you store a data item in cache, +you have to specify a key for it. Later when you retrieve the data item from cache, you should provide +the corresponding key. + +You may use a string or an arbitrary value as a cache key. When a key is not a string, it will be automatically +serialized into a string. + +A common strategy of defining a cache key is to include all determining factors in terms of an array. +For example, [[yii\db\Schema]] uses the following key to cache schema information about a database table: + +```php +[ + __CLASS__, // schema class name + $this->db->dsn, // DB connection data source name + $this->db->username, // DB connection login user + $name, // table name +]; +``` + +As you can see, the key includes all necessary information needed to uniquely specify a database table. + +When the same cache storage is used by different applications, you should specify a unique cache key prefix +for each application to avoid conflicts of cache keys. This can be done by configuring the [[yii\caching\Cache::keyPrefix]] +property. For example, in the application configuration you can write the following code: + +```php +'components' => [ + 'cache' => [ + 'class' => 'yii\caching\ApcCache', + 'keyPrefix' => 'myapp', // a unique cache key prefix + ], +], +``` + +To ensure interoperability, only alphanumeric characters should be used. + + +### Cache Expiration + +A data item stored in a cache will remain there forever unless it is removed because of some caching policy +enforcement (e.g. caching space is full and the oldest data are removed). To change this behavior, you can provide +an expiration parameter when calling [[yii\caching\Cache::set()|set()]] to store a data item. The parameter +indicates for how many seconds the data item can remain valid in the cache. When you call +[[yii\caching\Cache::get()|get()]] to retrieve the data item, if it has passed the expiration time, the method +will return false, indicating the data item is not found in the cache. For example, + +```php +// keep the data in cache for at most 45 seconds +$cache->set($key, $data, 45); + +sleep(50); + +$data = $cache->get($key); +if ($data === false) { + // $data is expired or is not found in the cache +} +``` + + +### Cache Dependencies + +Besides expiration setting, cached data item may also be invalidated by changes of the so-called *cache dependencies*. +For example, [[yii\caching\FileDependency]] represents the dependency of a file's modification time. +When this dependency changes, it means the corresponding file is modified. As a result, any outdated +file content found in the cache should be invalidated and the [[yii\caching\Cache::get()|get()]] call +should return false. + +Cache dependencies are represented as objects of [[yii\caching\Dependency]] descendant classes. When you call +[[yii\caching\Cache::set()|set()]] to store a data item in the cache, you can pass along an associated cache +dependency object. For example, + +```php +// Create a dependency on the modification time of file example.txt. +$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']); + +// The data will expire in 30 seconds. +// It may also be invalidated earlier if example.txt is modified. +$cache->set($key, $data, 30, $dependency); + +// The cache will check if the data has expired. +// It will also check if the associated dependency was changed. +// It will return false if any of these conditions is met. +$data = $cache->get($key); +``` + +Below is a summary of the available cache dependencies: + +- [[yii\caching\ChainedDependency]]: the dependency is changed if any of the dependencies on the chain is changed. +- [[yii\caching\DbDependency]]: the dependency is changed if the query result of the specified SQL statement is changed. +- [[yii\caching\ExpressionDependency]]: the dependency is changed if the result of the specified PHP expression is changed. +- [[yii\caching\FileDependency]]: the dependency is changed if the file's last modification time is changed. +- [[yii\caching\GroupDependency]]: marks a cached data item with a group name. You may invalidate the cached data items + with the same group name all at once by calling [[yii\caching\GroupDependency::invalidate()]]. + + +## Query Caching + +Query caching is a special caching feature built on top of data caching. It is provided to cache the result +of database queries. + +Query caching requires a [[yii\db\Connection|DB connection]] and a valid `cache` application component. +The basic usage of query caching is as follows, assuming `$db` is a [[yii\db\Connection]] instance: + +```php +$duration = 60; // cache query results for 60 seconds. +$dependency = ...; // optional dependency + +$db->beginCache($duration, $dependency); + +// ...performs DB queries here... + +$db->endCache(); +``` + +As you can see, any SQL queries in between the `beginCache()` and `endCache()` calls will be cached. +If the result of the same query is found valid in the cache, the query will be skipped and the result +will be served from the cache instead. + +Query caching can be used for [DAO](db-dao.md) as well as [ActiveRecord](db-active-record.md). + +> Info: Some DBMS (e.g. [MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html)) + also support query caching on the DB server side. You may choose to use either query caching mechanism. + The query caching described above has the advantage that you may specify flexible cache dependencies + and are potentially more efficient. + + +### Configurations + +Query caching has two two configurable options through [[yii\db\Connection]]: + +* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: this represents the number of seconds + that a query result can remain valid in the cache. The duration will be overwritten if you call + [[yii\db\Connection::beginCache()]] with an explicit duration parameter. +* [[yii\db\Connection::queryCache|queryCache]]: this represents the ID of the cache application component. + It defaults to `'cache'`. Query caching is enabled only when there is a valid cache application component. + + +### Limitations + +Query caching does not work with query results that contain resource handles. For example, +when using the `BLOB` column type in some DBMS, the query result will return a resource +handle for the column data. + +Some caching storage has size limitation. For example, memcache limits the maximum size +of each entry to be 1MB. Therefore, if the size of a query result exceeds this limit, +the caching will fail. +