瓦片缓存技术性能如何提高
Introduction
介绍
This article explores the design of a cache system that can improve the performance of a web site or web application. The assumption is that the web site has many more “read” operations than “write” operations (this is commonly the case for informational sites) and for this reason, the site should be able to recognize repeated identical requests and return an immediate cached response, rather than going back to the database queries for the reformulation of the original response.
本文探讨了可以提高网站或Web应用程序性能的缓存系统的设计。 假定该网站具有比“写”操作更多的“读”操作(这是信息网站的常见情况),因此,该网站应该能够识别重复的相同请求并返回立即缓存的响应,而不是返回数据库查询以重新构造原始响应。
The rationale for this strategy comes from recognition of the difference in speed between in-memory processes and disk-based processes. While memory access is typically measured in nanoseconds, even a very fast disk spinning at 7200RPM requires 8.3 milliseconds for a single rotation, and the nature of file lookup or database operations is such that a great many disk rotations may be required for some queries. Since the ratio of nanoseconds to milliseconds is several orders of magnitude, it follows that cache may produce substantial quantitative improvements in server performance.
此策略的基本原理是认识到内存中进程和基于磁盘的进程之间的速度差异。 虽然通常以纳秒为单位来衡量内存访问,但是即使以7200RPM的速度旋转非常快的磁盘,单次旋转也需要8.3毫秒,并且文件查找或数据库操作的性质使得某些查询可能需要大量磁盘旋转。 由于纳秒与毫秒的比率为几个数量级,因此可以得出结论,缓存可能会在服务器性能方面产生实质性的定量改进。
Characteristics of a Cache
缓存的特征
Popular cache systems include Memcached and Redis, and it is also possible to use the file system for cache storage, but in-memory systems will give the best performance. All cache systems work in similar ways. They are key:value data storage systems. Access to a value in the cache is made by reference to the key; the cache system associates the key with the value, much like the keys of an associative array or the property names of an object. The cache system provides for expiration of the cached values based on elapsed time since the key:value pair was most recently stored. The API for a cache system includes methods to put() information into the cache, get() information out of the cache, and delete() information from the cache. There may be other methods in the API, for example, Laravel offers a has() method to ask whether a key exists without actually returning the associated value. And our Cache Interface defines a flush() method to remove all data from the cache.
流行的缓存系统包括Memcached和Redis ,也可以将文件系统用于缓存存储,但是内存系统将提供最佳性能。 所有缓存系统都以类似的方式工作。 它们是Laravel提供了
Because there could be more than one concrete implementation of the cache, we will "code to the interface" and follow the standard practices of abstraction in object-oriented design. By doing our design this way we can write code that uses the cache without any need to concern ourselves with the exact implementation of the cache. Interface-driven design has several advantages. One obvious advantage is that the programmers who agree upon the interface can work independently to develop the implementations and the use cases. Although we are using the PHP session in our demonstration script below, we could easily switch to Redis by replacing only the CacheDemo class. None of the rest of our script would require a change.
因为可能有多个缓存的具体实现,所以我们将“编码到接口”并遵循面向对象设计中抽象的标准做法。 通过以这种方式进行设计,我们可以编写使用缓存的代码,而无需担心缓存的确切实现。 接口驱动的设计具有多个优点。 一个明显的优点是,同意该接口的程序员可以独立工作以开发实现和用例。 尽管我们在下面的演示脚本中使用了PHP会话,但是通过替换CacheDemo类,我们可以轻松地切换到Redis。 我们脚本的其余部分都不需要更改。
A simple example of the cache API is shown here:
缓存API的简单示例如下所示:
<?php
/**
* A Cache API
*/
error_reporting(E_ALL);
Interface Cache
{
public static function put($key, $value, $duration);
public static function get($key);
public static function delete($key);
public static function flush();
}
Using the Cache
使用缓存
When the server receives a request, it can check the cache to see if the requested resource is available. A call to the get() method will return the resource or FALSE, if the key does not exist. When the server must generate a resource from database queries or other time-consuming activities, it can store the generated resource in the cache with a call to the put() method. The call to put() provides the key and value to be stored, as well as a duration in seconds. The keys in the cache are unique; a put() with a key that matches an existing resource will overwrite the stored data. When the server needs to remove a resource from the cache, a call to delete() with the named key will eliminate the cached resource. In certain circumstances it may be necessary to remove all cached information; the flush() method will remove all resources resulting in an empty cache.
服务器收到请求后,可以检查缓存以查看请求的资源是否可用。 如果键不存在,则调用get()方法将返回资源或FALSE。 当服务器必须通过数据库查询或其他耗时的活动生成资源时,它可以通过调用put()方法将生成的资源存储在缓存中。 对put()的调用提供了要存储的键和值,以及以秒为单位的持续时间。 缓存中的键是唯一的; 带有与现有资源匹配的键的put()将覆盖存储的数据。 当服务器需要从缓存中删除资源时,使用命名键调用delete()将消除缓存的资源。 在某些情况下,可能有必要删除所有缓存的信息; flush()方法将删除所有资源,从而导致缓存为空。
A “resource” can be any data element that the application needs to store. It might be a query results set, a web page fragment, or even an entire web page – HTML and all. A key can be any data element that the application needs to identify. It can be an entire HTTP request, identified by the full URL and query string. In the WWW, a RESTful design, a GET-method request is made by the web browser to a URL and the server responds with a web page containing the requested information. It follows that a web page made up from several complex queries, API calls, etc., can be an excellent candidate for cache storage.
“资源”可以是应用程序需要存储的任何数据元素。 它可能是查询结果集,网页片段,甚至是整个网页-HTML等。 密钥可以是应用程序需要识别的任何数据元素。 它可以是一个完整的HTTP请求,由完整的URL和查询字符串标识。 在WWW中,这是一种RESTful设计,Web浏览器向URL发出GET方法请求,服务器用包含所请求信息的网页进行响应。 因此,由几个复杂的查询,API调用等组成的网页可能是缓存存储的理想选择。
A cached resource is considered to be an element. It cannot be subdivided or augmented; it can only be added, removed or replaced. A cached resource can be represented by an object instance of the CacheElement class:
缓存的资源被视为元素。 它不能细分或扩充; 只能添加,删除或替换它。 高速缓存的资源可以由CacheElement类的对象实例表示:
Class CacheElement
{
public $key;
public $value;
public $expiry;
public function __construct($key, $value, $duration)
{
$this->key = $key;
$this->value = $value;
$this->expiry = time() + $duration;
}
}
A Concrete Implementation of the Cache Methods
缓存方法的具体实现
Each cache element is represented by a CacheElement object.
每个缓存元素由一个CacheElement对象表示。
The put() method stores a CacheElement object in the collection of elements, using the key to create or overwrite any existing element with a matching key.
put()方法将CacheElement对象存储在元素集合中,使用该键创建或覆盖具有匹配键的任何现有元素。
The delete() method removes the CacheElement object with the matching key, and removes the key from the collection.
delete()方法使用匹配的键删除CacheElement对象,并从集合中删除键。
The flush() method removes all CacheElement objects and removes all keys from the collection.
flush()方法删除所有CacheElement对象,并从集合中删除所有键。
The get() method attempts to locate the element associated with the key argument. If no matching key is found, it returns FALSE. If a matching key is found in the collection, get() checks the current time against the expiration time of the CacheElement object. If the object has not expired, get() returns the value property. If the object has expired, it calls delete() and returns FALSE.
get()方法尝试查找与key参数关联的元素。 如果找不到匹配的密钥,则返回FALSE。 如果在集合中找到匹配的键,则get()会根据CacheElement对象的过期时间检查当前时间。 如果对象尚未过期,则get()返回value属性。 如果对象已过期,它将调用delete()并返回FALSE。
For methods other than get() the return value is undefined. Here is the code that implements the Cache:
对于除get()之外的方法,返回值是不确定的。 以下是实现缓存的代码:
Class CacheDemo implements Cache
{
public static function put($key, $value, $duration)
{
$_SESSION['cache_data'][$key] = new CacheElement($key, $value, $duration);
}
public static function get($key)
{
if (empty($_SESSION['cache_data'][$key])) return FALSE;
if ($_SESSION['cache_data'][$key]->expiry > time()) return $_SESSION['cache_data'][$key]->value;
self::delete($key);
return FALSE;
}
public static function delete($key)
{
unset($_SESSION['cache_data'][$key]);
}
public static function flush()
{
foreach ($_SESSION['cache_data'] as $key => $element)
{
self::delete($key);
}
}
}
A Simulation Strategy to Show the Value of Cache in Action
一种模拟策略来显示高速缓存的价值
For our example we will use the PHP session as the cache storage repository. This is not as high-performance as Memcached or Redis, but it will provide a durable and stateful data storage tool that will allow us to make a few requests, and thereby see the behavior and value of cache. We simulate the complexity and time requirements of uncached data requests by using PHP sleep() to add a few seconds to each request that cannot be satisfied by cache. As each response is created, it will be cached. The cached responses will be stored in an array of objects located at $_SESSION[‘cache_data’].
对于我们的示例,我们将使用PHP会话作为缓存存储库。 它不像Memcached或Redis那样高性能,但是它将提供一个持久且有状态的数据存储工具,使我们可以发出一些请求,从而了解缓存的行为和价值。 通过使用PHP sleep()向未通过缓存满足的每个请求增加几秒钟的时间,我们模拟了未缓存数据请求的复杂性和时间要求。 创建每个响应时,将对其进行缓存。 缓存的响应将存储在位于$ _SESSION ['cache_data']的对象数组中。
Our simulation script will be intentionally very simple so we can illustrate the cache behavior without other activities that might distract from the message. The script will use the GET argument, key=, to determine its action. If the key is omitted or empty, the script will do nothing. If key==flush, the script will flush the cache.
我们的模拟脚本故意非常简单,因此我们可以说明缓存行为,而无需其他可能分散消息的活动。 该脚本将使用GET参数
For all other values of key= the script will act like a well-behaved web server that is aware of its ability to cache responses. It will attempt to get() a matching response from the cache, and will return the cached response if one is available. Failing that, it will generate the response (a slow process) and store the response in the cache before returning the response. Subsequent requests can then be satisfied from cache (a fast process) until the cache expires and the response must be regenerated.
对于
Here is the complete demonstration script. You can copy it and install it on your own server to study, test and experiment.
这是完整的演示脚本。 您可以将其复制并安装到自己的服务器上以进行学习,测试和实验。
<?php // demo/EE_cache_demo.php
/**
* A Cache API
*/
error_reporting(E_ALL);
Interface Cache
{
public static function put($key, $value, $duration);
public static function get($key);
public static function delete($key);
public static function flush();
}
Class CacheElement
{
public $key;
public $expiry;
public $value;
public function __construct($key, $value, $duration)
{
$this->key = $key;
$this->value = $value;
$this->expiry = time() + $duration;
}
}
Class CacheDemo implements Cache
{
public static function put($key, $value, $duration)
{
$_SESSION['cache_data'][$key] = new CacheElement($key, $value, $duration);
}
public static function get($key)
{
if (empty($_SESSION['cache_data'][$key])) return FALSE;
if ($_SESSION['cache_data'][$key]->expiry > time()) return $_SESSION['cache_data'][$key]->value;
self::delete($key);
return FALSE;
}
public static function delete($key)
{
unset($_SESSION['cache_data'][$key]);
}
public static function flush()
{
foreach ($_SESSION['cache_data'] as $key => $element)
{
self::delete($key);
}
}
}
// WE USE THE PHP SESSION FOR THE CACHE
session_start();
// THE ACTIONS THAT CAN BE PERFORMED BY THIS SCRIPT
$key = (!empty($_GET['key'])) ? strtolower($_GET['key']) : NULL;
// SPECIAL CASE KEY: OMITTED
if (!$key) die('No key');
// SPECIAL CASE KEY: FLUSH THE CACHE
if ($key == 'flush')
{
CacheDemo::flush();
$response = 'At ' . date('H:i:s') . ', the cache was flushed';
die($response);
}
// TRY THE CACHE FOR THIS KEY
$response = CacheDemo::get($key);
// IF THE RESPONSE HAS BEEN CACHED
if ($response)
{
die('Retrieved from cache at ' . date('H:i:s ') . $response);
}
// IF NO CACHED REPRESENTATION IS AVAILABLE YET
else
{
// PRETEND IT TAKES A LONG TIME TO GENERATE THIS COMPLICATED RESPONSE
sleep(3);
// CREATE THE RESPONSE AND CACHE IT FOR HALF A MINUTE
$response = 'This response to the request for: ' . $key . ' was created at ' . date('H:i:s');
CacheDemo::put($key, $response, 30);
// RETURN THE NEWLY CREATED RESPONSE
die($response);
}
What Happens in Practice?
在实践中会发生什么?
We can see the behavior illustrated in these screen shots that include the browser URL, the browser output, and the console. First, we flush the cache. This is a fast process, returning a complete response in less than 1/10 second..
我们可以看到这些屏幕快照中显示的行为,其中包括浏览器URL,浏览器输出和控制台。 首先,我们刷新缓存。 这是一个快速的过程,可以在不到1/10秒的时间内返回完整的响应。
![flush-cache.png](https://i-blog.csdnimg.cn/blog_migrate/9e32ca3befa264db19f10c564a1288ed.png)
Next we make a request for a page that is not cached. As we can see, this is a slow process. The console shows us that the request was not completed for more than three seconds. But we have a bright future for the next request to this URL.
接下来,我们请求一个未缓存的页面。 如我们所见,这是一个缓慢的过程。 控制台向我们显示请求未完成超过三秒钟。 但是,对于该URL的下一个请求,我们有美好的未来。
![slow-response-before-cache.png](https://i-blog.csdnimg.cn/blog_migrate/c2eed6315f9e5e7f0d81321dfa3cab3a.png)
When we reqest the same resource again, we see a nearly instantaneous response. Because the data was in the cache, we are able to return it without any delay. From the timestamp at the end of the response, we can see that this is the same response data we created above. Instead of taking three seconds to generate the page, the cached response was completed in less than 1/10 second.
当我们再次请求相同的资源时,我们看到了几乎瞬时的响应。 因为数据在缓存中,所以我们可以立即返回它。 从响应末尾的时间戳,我们可以看到这与我们上面创建的响应数据相同。 无需花费三秒钟的时间来生成页面,而是在不到1/10秒的时间内完成了缓存的响应。
![fast-response-from-cache.png](https://i-blog.csdnimg.cn/blog_migrate/2d7c99f9fa59ce3f2a5a56c2056b7039.png)
After a period of time, the cache expiration will have passed, and the page must be regenerated. When that happens it will again take a long time to generate the page, but there will be a new timestamp on the end of the response, showing that we have gotten the latest data from the server.
一段时间后,缓存过期将过去,并且必须重新生成页面。 发生这种情况时,将再次花费很长时间来生成页面,但是响应的末尾会有新的时间戳,表明我们已从服务器获取了最新数据。
![after-cache-expiration.png](https://i-blog.csdnimg.cn/blog_migrate/4a90ddb43463f5e078f1a84cafc7f440.png)
Summary
摘要
This article has shown the design and desirability of a server-side cache algorithm. The benefits of cache include faster responses to the client, decreased loads on the server, and reduced calls to external APIs. Cache is appropriate whenever generation of a web page is "slow" relative to the arrival of requests. In a heavily used web site, even a short-term cache can provide great performance benefits. Cache is also appropriate when there is a desire to capture an "image" of a web resource and serve the same image over a period of time, for example, a church sermon that only changes weekly. In contrast, cache is inappropriate in a test and development environment, where an exact representation of each server response is necessary for debugging new code. But once an application is deployed, the ability to cache the server responses can provide great improvements in performance at very little cost.
本文介绍了服务器端缓存算法的设计和合意性。 缓存的好处包括对客户端的响应速度更快,服务器上的负载减少以及对外部API的调用减少。 每当网页的生成相对于请求的到达“缓慢”时,缓存都是合适的。 在频繁使用的网站中,即使是短期缓存也可以提供巨大的性能优势。 当希望捕获Web资源的“图像”并在一段时间内提供相同的图像(例如每周仅更改一次的教堂讲道)时,缓存也是合适的。 相反,缓存在测试和开发环境中是不合适的,在测试和开发环境中,每个服务器响应的准确表示对于调试新代码是必需的。 但是,一旦部署了应用程序,就可以以很少的成本缓存服务器响应的能力极大地提高了性能。
Please give us your feedback!
请给我们您的反馈意见!
If you found this article helpful, please click the "thumb's up" button below. Doing so lets the E-E community know what is valuable for E-E members and helps provide direction for future articles. If you have questions or comments, please add them. Thanks!
如果您发现本文有帮助,请单击下面的“竖起大拇指”按钮。 这样做可以使EE社区了解对EE成员有价值的内容,并为将来的文章提供指导。 如果您有任何问题或意见,请添加。 谢谢!
翻译自: https://www.experts-exchange.com/articles/18437/Improving-Web-Site-Performance-via-PHP-Cache.html
瓦片缓存技术性能如何提高