使用Redis在Django中缓存

django redis cache

Application performance is vital to the success of your product. In an environment where users expect website response times of less than a second, the consequences of a slow application can be measured in dollars and cents. Even if you are not selling anything, fast page loads improve the experience of visiting your site.

应用程序性能对于产品成功至关重要。 在用户期望网站响应时间少于一秒的环境中 ,应用程序运行缓慢的后果可以用美元和美分来衡量。 即使您什么都没卖,快速的页面加载也可以改善访问站点的体验。

Everything that happens on the server between the moment it receives a request to the moment it returns a response increases the amount of time it takes to load a page. As a general rule of thumb, the more processing you can eliminate on the server, the faster your application will perform. Caching data after it has been processed and then serving it from the cache the next time it is requested is one way to relieve stress on the server. In this tutorial, we will explore some of the factors that bog down your application, and we will demonstrate how to implement caching with Redis to counteract their effects.

从接收请求到返回响应之间,服务器上发生的所有事情都会增加加载页面所需的时间。 根据一般经验,可以在服务器上消除的处理越多,应用程序执行的速度就越快。 处理数据后缓存数据,然后在下次请求时从缓存中提供数据是缓解服务器压力的一种方法。 在本教程中,我们将探讨使您的应用程序陷入困境的一些因素,并将演示如何使用Redis实施缓存以抵消其影响。

什么是Redis? (What is Redis?)

Redis is an in-memory data structure store that can be used as a caching engine. Since it keeps data in RAM, Redis can deliver it very quickly. Redis is not the only product that we can use for caching. Memcached is another popular in-memory caching system, but many people agree that Redis is superior to Memcached in most circumstances. Personally, we like how easy it is to set up and use Redis for other purposes such as Redis Queue.

Redis是一种内存数据结构存储,可以用作缓存引擎。 由于它将数据保留在RAM中,因此Redis可以非常快速地交付数据。 Redis不是唯一可以用于缓存的产品。 Memcached是另一种流行的内存缓存系统,但是许多人同意Redis在大多数情况下都优于Memcached 。 就个人而言,我们喜欢设置和使用Redis进行其他用途(例如Redis Queue)是多么容易。

入门 (Getting Started)

We have created an example application to introduce you to the concept of caching. Our application uses:

我们创建了一个示例应用程序,向您介绍了缓存的概念。 我们的应用程序使用:

  • Django(v 1.9.8
  • Django调试工具栏(v 1.4
  • django-redis(v 4.4.3
  • Redis(v 3.2.0

安装应用 (Install the App)

Before you clone the repository, install virtualenvwrapper, if you don’t already have it. This is a tool that lets you install the specific Python dependencies that your project needs, allowing you to target the versions and libraries required by your app in isolation.

克隆存储库之前,请安装virtualenvwrapper (如果尚未安装)。 这是一个工具,可让您安装项目所需的特定Python依赖关系,从而使您可以单独定位应用程序所需的版本和库。

Next, change directories to where you keep projects and clone the example app repository. Once done, change directories to the cloned repository, and then make a new virtual environment for the example app using the mkvirtualenv command:

接下来,将目录更改为保存项目的位置,然后克隆示例应用程序存储库。 完成后,将目录更改为克隆的存储库,然后使用mkvirtualenv命令为示例应用程序创建新的虚拟环境:

1
1
2
2

NOTE: Creating a virtual environment with mkvirtualenv also activates it.

注意:使用mkvirtualenv创建虚拟环境也会激活它。

Install all of the required Python dependencies with pip, and then checkout the following tag:

使用pip安装所有必需的Python依赖项,然后签出以下标记:

1
1

Finish setting up the example app by building the database and populating it with sample data. Make sure to create a superuser too, so that you can log into the admin site. Follow the code examples below and then try running the app to make sure it is working correctly. Visit the admin page in the browser to confirm that the data has been properly loaded.

通过构建数据库并用示例数据填充它来完成示例应用程序的设置。 确保也创建一个超级用户,以便您可以登录到管理站点。 请遵循以下代码示例,然后尝试运行该应用程序以确保其正常运行。 在浏览器中访问管理页面,以确认数据已正确加载。

1
1
2
2
3
3
4
4

Once you have the Django app running, move onto the Redis installation.

运行Django应用后,转到Redis安装。

安装Redis (Install Redis)

Download and install Redis using the instructions provided in the documentation. Alternatively, you can install Redis using a package manager such as apt-get or homebrew depending on your OS.

使用文档中提供的说明下载并安装Redis 。 另外,您可以根据操作系统使用软件包管理器(如apt-get或homebrew)安装Redis。

Run the Redis server from a new terminal window.

从新的终端窗口运行Redis服务器。

1
1

Next, start up the Redis command-line interface (CLI) in a different terminal window and test that it connects to the Redis server. We will be using the Redis CLI to inspect the keys that we add to the cache.

接下来,在另一个终端窗口中启动Redis命令行界面(CLI),并测试它是否连接到Redis服务器。 我们将使用Redis CLI来检查添加到缓存中的密钥。

1
1
2
2

Redis provides an API with various commands that a developer can use to act on the data store. Django uses django-redis to execute commands in Redis.

Redis为API提供了各种命令,开发人员可以使用它们对数据存储执行操作。 Django使用django-redis在Redis中执行命令。

Looking at our example app in a text editor, we can see the Redis configuration in the settings.py file. We define a default cache with the CACHES setting, using a built-in django-redis cache as our backend. Redis runs on port 6379 by default, and we point to that location in our setting. One last thing to mention is that django-redis appends key names with a prefix and a version to help distinguish similar keys. In this case, we have defined the prefix to be “example”.

在文本编辑器中查看示例应用程序,我们可以在settings.py文件中看到Redis配置。 我们使用CACHES设置定义默认的缓存,并使用内置的django-redis缓存作为我们的后端。 默认情况下,Redis在端口6379上运行,我们在设置中指向该位置。 最后要提到的是django-redis在键名后附加前缀和版本,以帮助区分相似的键。 在这种情况下,我们将前缀定义为“ example”。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10

NOTE: Although we have configured the cache backend, none of the view functions have implemented caching.

注意 :尽管我们已经配置了缓存后端,但是所有视图功能都没有实现缓存。

应用程式效能 (App Performance)

As we mentioned at the beginning of this tutorial, everything that the server does to process a request slows the application load time. The processing overhead of running business logic and rendering templates can be significant. Network latency affects the time it takes to query a database. These factors come into play every time a client sends an HTTP request to the server. When users are initiating many requests per second, the effects on performance become noticeable as the server works to process them all.

正如我们在本教程开始时提到的那样,服务器处理请求的所有操作都会减慢应用程序的加载时间。 运行业务逻辑和呈现模板的处理开销可能很大。 网络延迟会影响查询数据库所需的时间。 每当客户端向服务器发送HTTP请求时,这些因素都会起作用。 当用户每秒发起许多请求时,随着服务器努力处理所有请求,对性能的影响将变得明显。

When we implement caching, we let the server process a request once and then we store it in our cache. As requests for the same URL are received by our application, the server pulls the results from the cache instead of processing them anew each time. Typically, we set a time to live on the cached results, so that the data can be periodically refreshed, which is an important step to implement in order to avoid serving stale data.

当实现缓存时,我们让服务器处理一次请求,然后将其存储在缓存中。 当我们的应用程序收到对相同URL的请求时,服务器会从缓存中提取结果,而不是每次都重新处理它们。 通常,我们为缓存的结果设置一个生存时间,以便可以定期刷新数据,这是要执行的重要步骤,以避免提供过时的数据。

You should consider caching the result of a request when the following cases are true:

如果满足以下情况,则应考虑缓存请求的结果:

  • rendering the page involves a lot of database queries and/or business logic,
  • the page is visited frequently by your users,
  • the data is the same for every user,
  • and the data does not change often.
  • 呈现页面涉及很多数据库查询和/或业务逻辑,
  • 您的用户经常访问该页面,
  • 每个用户的数据都是相同的
  • 并且数据不会经常更改。

从衡量绩效开始 (Start by Measuring Performance)

Begin by testing the speed of each page in your application by benchmarking how quickly your application returns a response after receiving a request.

首先通过基准测试应用程序在收到请求后返回响应的速度来测试应用程序中每个页面的速度。

To achieve this, we’ll be blasting each page with a burst of requests using loadtest, an HTTP load generator, and then paying close attention to the request rate. Visit the link above to install. Once installed, test the results against the /cookbook/ URL path:

为了实现这一点,我们将使用HTTP Load Generator HTTP, loadtest对每个页面进行大量请求,然后密切关注请求率。 请访问上面的链接进行安装。 安装完成后,对照/cookbook/ URL路径测试结果:

1
1

Notice that we are processing about 16 requests per second:

请注意,我们每秒处理大约16个请求:

1
1

When we look at what the code is doing, we can make decisions on how to make changes to improve the performance. The application makes 3 network calls to a database with each request to /cookbook/, and it takes time for each call to open a connection and execute a query. Visit the /cookbook/ URL in your browser and expand the Django Debug Toolbar tab to confirm this behavior. Find the menu labeled “SQL” and read the number of queries:

当我们查看代码在做什么时,我们可以决定如何进行更改以提高性能。 该应用程序对/cookbook/每个请求都会对数据库进行3次网络调用,并且每次调用都需要时间才能打开连接并执行查询。 在浏览器中访问/cookbook/ URL并展开Django Debug Toolbar选项卡以确认此行为。 找到标有“ SQL”的菜单并读取查询数量:

django debug framework sql queries

cookbook/services.py

cookbook / services.py

1
1
2
2
3
3
4
4
5
5
6
6
7
7

cookbook/views.py

食谱/views.py

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8

The application also renders a template with some potentially expensive logic.

该应用程序还使用一些可能昂贵的逻辑来渲染模板。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19

实施缓存 (Implement Caching)

Imagine the total number of network calls that our application will make as users start to visit our site. If 1,000 users hit the API that retrieves cookbook recipes, then our application will query the database 3,000 times and a new template will be rendered with each request. That number only grows as our application scales. Luckily, this view is a great candidate for caching. The recipes in a cookbook rarely change, if ever. Also, since viewing cookbooks is the central theme of the app, the API retrieving the recipes is guaranteed to be called frequently.

想象一下,当用户开始访问我们的网站时,我们的应用程序将进行的网络呼叫总数。 如果有1,000个用户点击检索菜谱食谱的API,则我们的应用程序将查询数据库3,000次,并且每次请求都会呈现一个新模板。 这个数字只会随着我们应用程序的扩展而增长。 幸运的是,此视图非常适合缓存。 食谱中的食谱很少更改(如果有的话)。 另外,由于查看食谱是该应用程序的中心主题,因此可以确保经常调用检索食谱的API。

In the example below, we modify the view function to use caching. When the function runs, it checks if the view key is in the cache. If the key exists, then the app retrieves the data from the cache and returns it. If not, Django queries the database and then stashes the result in the cache with the view key. The first time this function is run, Django will query the database and render the template, and then will also make a network call to Redis to store the data in the cache. Each subsequent call to the function will completely bypass the database and business logic and will query the Redis cache.

在下面的示例中,我们将视图功能修改为使用缓存。 该函数运行时,它将检查视图键是否在缓存中。 如果密钥存在,则应用程序从缓存中检索数据并返回。 如果不是,Django将查询数据库,然后将结果与视图键一起存储在缓存中。 第一次运行此功能时,Django将查询数据库并渲染模板,然后还将对Redis进行网络调用以将数据存储在缓存中。 随后对该函数的每次调用将完全绕过数据库和业务逻辑,并将查询Redis缓存。

example/settings.py

example / settings.py

1
1
2
2

cookbook/views.py

食谱/views.py

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14

Notice that we have added the @cache_page() decorator to the view function, along with a time to live. Visit the /cookbook/ URL again and examine the Django Debug Toolbar. We see that 3 database queries are made and 3 calls are made to the cache in order to check for the key and then to save it. Django saves two keys (1 key for the header and 1 key for the rendered page content). Reload the page and observe how the page activity changes. The second time around, 0 calls are made to the database and 2 calls are made to the cache. Our page is now being served from the cache!

请注意,我们已经将@cache_page()装饰器添加到了视图函数中,并且还有一个生存时间。 再次访问/cookbook/ URL,并检查Django Debug Toolbar。 我们看到进行了3个数据库查询,并对高速缓存进行了3次调用,以检查密钥并保存。 Django保存了两个键(标题为1键,渲染页面内容为1键)。 重新加载页面并观察页面活动如何变化。 第二次,对数据库进行了0次调用,对缓存进行了2次调用。 现在正在从缓存中提供我们的页面!

When we re-run our performance tests, we see that our application is loading faster.

当我们重新运行性能测试时,我们看到我们的应用程序加载得更快。

1
1

Caching improved the total load, and we are now resolving 21 requests per second, which is 5 more than our baseline:

缓存改善了总负载,我们现在每秒可以解决21个请求,这比我们的基线多了5个:

1
1

使用CLI检查Redis (Inspecting Redis with the CLI)

At this point we can use the Redis CLI to look at what gets stored on the Redis server. In the Redis command-line, enter the keys * command, which returns all keys matching any pattern. You should see a key called “example:1:views.decorators.cache.cache_page”. Remember, “example” is our key prefix, “1” is the version, and “views.decorators.cache.cache_page” is the name that Django gives the key. Copy the key name and enter it with the get command. You should see the rendered HTML string.

此时,我们可以使用Redis CLI查看Redis服务器上存储的内容。 在Redis命令行中,输入keys *命令,该命令将返回与任何模式匹配的所有键。 您应该看到一个名为“ example:1:views.decorators.cache.cache_page”的键。 请记住,“ example”是我们的键前缀,“ 1”是版本,“ views.decorators.cache.cache_page”是Django提供键的名称。 复制密钥名称,然后使用get命令输入密钥名称。 您应该看到呈现HTML字符串。

1
1
2
2
3
3
4
4
5
5

NOTE: Run the flushall command on the Redis CLI to clear all of the keys from the data store. Then, you can run through the steps in this tutorial again without having to wait for the cache to expire.

注意:在Redis CLI上运行flushall命令,以清除数据存储中的所有键。 然后,您可以再次执行本教程中的步骤,而不必等待缓存过期。

结语 (Wrap-up)

翻译自: https://www.pybloggers.com/2016/09/caching-in-django-with-redis/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值