Статьи

Как кэшировать с помощью Redis в приложениях Django

Одним из способов снять нагрузку на сервер является кэширование данных. Это делается путем кэширования данных после их обработки и последующего обслуживания из кэша при следующем запросе. В этом руководстве будет подробно рассказано о Redis и объяснено, как устанавливать Redis и кэшировать данные в приложениях Python.

Кэширование относится к хранению ответа сервера в самом клиенте, поэтому клиенту не нужно снова и снова запрашивать у сервера один и тот же ресурс. Ответ сервера должен содержать информацию о том, как должно выполняться кэширование, чтобы клиент кэшировал ответ в течение определенного периода времени или никогда не кэшировал ответ сервера.

Кеш, с другой стороны, представляет собой аппаратный или программный компонент, который используется для хранения данных, чтобы будущие запросы на те же данные могли обслуживаться быстрее.

В этом возрасте, когда пользователи ожидают результатов в течение секунды, целесообразно обслуживать запросы, читая данные из кэша, что в конечном итоге быстрее, чем чтение из более медленного хранилища данных; Таким образом, производительность системы зависит от того, сколько запросов может быть обслужено из кэша.

Redis — это хранилище структуры данных с открытым исходным кодом, используемое в качестве базы данных, кэша и посредника сообщений. Он работает, храня данные в кэше и предоставляя их при следующем запросе, вместо того, чтобы каждый раз запрашивать базу данных.

Первый шаг — установить Redis и запустить его локально на вашей машине. Самый простой способ установить Redis — через менеджер пакетов операционной системы, например:

1
sudo apt-get install redis-server

Вы также можете следовать инструкциям с официального сайта Redis.

Скачайте и распакуйте Redis 4.0.6 tar следующим образом:

1
$ wget https://download.redis.io/releases/redis-4.0.6.tar.gz $ tar xzf redis-4.0.6.tar.gz $ cd redis-4.0.6 $ make

Двоичные файлы, которые теперь скомпилированы, доступны в каталоге src. Запустите Redis с:

1
$ src/redis-server

Вы можете взаимодействовать с Redis, используя встроенный клиент:

1
2
3
$ src/redis-cli
redis set foo bar OK redis
get foo «bar»

Чтобы проверить, работает ли сервер redis, введите в терминале следующую команду:

1
2
$ sudo redis-server
* Ready to accept connections

Давайте создадим наш проект Django. Наш проект сможет кэшировать все товары в магазине, что позволяет легко и быстро получать данные в последующих запросах.

Чтобы использовать Redis в нашем приложении, нам нужно сделать следующее:

  1. Проверьте, есть ли результаты для текущего запроса в кэше.
  2. Если в кеше есть результаты, восстановите их.
  3. Если результатов не существует, извлеките их, сохраните в кеше, а затем отправьте их запрашивающему объекту.
  • Джанго
  • Джанго-Redis
  • Redis
  • LoadTest

Прежде чем мы начнем, создайте каталог и установите виртуальную среду. Виртуальная среда позволит вам установить версии библиотеки, необходимые для вашего приложения.

1
2
3
mkdir myprojects
 
cd myprojects

Далее активируйте виртуальную среду и установите требования проекта.

1
2
3
4
5
6
7
source venv/bin/activate
 
pip install django==1.9
 
pip install django-redis
 
pip install djangorestframework
1
django-admin startproject django_cache

Создайте новое приложение под названием store, которое будет управлять товаром в нашем магазине.

1
2
3
cd django_cache
 
python manage.py startapp store

Добавьте приложение store и rest_framework в список установленных приложений в файле settings.py .

01
02
03
04
05
06
07
08
09
10
11
# settings.py
INSTALLED_APPS = [
    ‘django.contrib.admin’,
    ‘django.contrib.auth’,
    ‘django.contrib.contenttypes’,
    ‘django.contrib.sessions’,
    ‘django.contrib.messages’,
    ‘django.contrib.staticfiles’,
    ‘store’, # add here
    ‘rest_framework’, # add here too
]

В store/models.py мы начинаем с создания модели Product для хранения сведений о продукте следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from __future__ import unicode_literals
from django.db import models
import datetime
 
# Create your models here.
 
 
class Product(models.Model):
 
    name = models.CharField(max_length=255)
    description = models.TextField(null=True, blank=True)
    price = models.IntegerField(null=True, blank=True)
    date_created = models.DateTimeField(auto_now_add=True, blank=True)
    date_modified = models.DateTimeField(auto_now=True, blank=True)
 
    def __unicode__(self):
        return self.name
 
    def to_json(self):
        return {
            ‘id’: self.id,
            ‘name’: self.name,
            ‘desc’: self.description,
            ‘price’: self.price,
            ‘date_created’: self.date_created,
            ‘date_modified’: self.date_modified
        }

Создайте начальную миграцию для нашей модели продуктов и впервые синхронизируйте базу данных.

1
2
3
python manage.py makemigration store
 
python manage.py migrate

Создайте суперпользователя, войдите в панель администратора и заполните свою базу данных некоторыми примерами данных, которые мы будем использовать для наших тестов.

1
python manage.py createsuperuser

Чтобы использовать Redis с приложением Django, нам нужно настроить Redis для хранения данных кэша приложения. И следующее к вашему файлу settings.py :

1
2
3
4
5
6
7
8
9
CACHES = {
    ‘default’: {
        ‘BACKEND’: ‘django_redis.cache.RedisCache’,
        ‘LOCATION’: ‘redis://127.0.0.1:6379/’,
        ‘OPTIONS’: {
            ‘CLIENT_CLASS’: ‘django_redis.client.DefaultClient’,
        }
    }
}

Далее мы собираемся создать конечную точку, которая извлекает все продукты из нашей базы данных. Сначала мы проверим производительность приложения с точки зрения того, сколько времени требуется для извлечения данных из базы данных без ее кэширования. Затем мы реализуем другую конечную точку, которая извлекает данные из кэша и сравнивает производительность.

В store/views.py добавьте следующий код, который извлекает все продукты, присутствующие в базе данных.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
 
# Create your views here.
 
 
 
@api_view([‘GET’])
def view_books(request):
 
    products = Product.objects.all()
    results = [product.to_json() for product in products]
    return Response(results, status=status.HTTP_201_CREATED)

Создайте файл store/urls.py и добавьте следующий код.

1
2
3
4
5
6
7
8
# store/urls.py
from django.conf.urls import url
from .views import view_books
 
 
urlpatterns = [
    url(r’^$’, view_books),
]

Нам также необходимо импортировать URL-адреса из пользовательского приложения в основной django_cache/urls.py

1
2
3
4
5
6
7
8
9
# django_cache/urls.py
 
from django.conf.urls import url, include
from django.contrib import admin
 
urlpatterns = [
    url(r’^admin/’, admin.site.urls),
    url(r’^store/’, include(‘store.urls’))
]

Давайте сделаем тест и посмотрим, на правильном ли мы пути. Мы будем использовать loadtest . Если вы не знакомы с loadtest, это инструмент для тестирования производительности.

Установить loadtest от имени root просто:

1
sudo npm install -g loadtest
1
2
3
4
$ loadtest -n 100 -k http://localhost:8000/store/
 
# result
INFO Requests per second: 55

Как видно из вышеизложенного, в секунду обрабатывается 55 запросов.

Давайте создадим еще одну конечную точку для извлечения данных после кэширования с помощью Redis. Отредактируйте users/views.py чтобы соответствовать следующему:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from rest_framework.decorators import api_view
from rest_framework import status
from rest_framework.response import Response
from django.core.cache import cache
from django.conf import settings
from django.core.cache.backends.base import DEFAULT_TIMEOUT
 
CACHE_TTL = getattr(settings, ‘CACHE_TTL’, DEFAULT_TIMEOUT)
from .models import Product
 
 
# Create your views here.
 
 
@api_view([‘GET’])
def view_books(request):
    # rest of the code
 
 
@api_view([‘GET’])
def view_cached_books(request):
    if ‘product’ in cache:
        # get results from cache
        products = cache.get(‘product’)
        return Response(products, status=status.HTTP_201_CREATED)
 
    else:
        products = Product.objects.all()
        results = [product.to_json() for product in products]
        # store data in cache
        cache.set(product, results, timeout=CACHE_TTL)
        return Response(results, status=status.HTTP_201_CREATED)

Приведенный выше код проверит, присутствует ли ключевой продукт в кэше, и, если он найден, представленные данные будут возвращены в браузер. Если в кеше нет данных, мы сначала извлекаем данные из базы данных, сохраняем их в кеше, а затем возвращаем запрашиваемые данные в браузер.

Обновите store/urls.py следующим образом.

1
2
3
4
5
6
7
8
9
from django.conf.urls import url
from .views import view_books, view_cached_books
 
 
urlpatterns = [
    url(r’^$’, view_books),
    url(r’^cache/’, view_cached_books),
 
]

Давайте проведем тесты.

1
2
3
4
$ loadtest -n 100 -k http://localhost:8000/store/cache/
 
# results
INFO Requests per second: 233

При первом обращении к конечной точке localhost: 8000 / store / cache приложение будет запрашивать данные из базы данных и возвращать данные, но последующие обращения к URL-адресу будут обходить базу данных и запрашивать данные из кэша, поскольку данные уже доступны в кэше. ,

В этом уроке мы использовали Redis, чтобы дать приложению иллюзию скорости. Мы используем использование ОЗУ в Redis для хранения результатов запросов, а затем возвращаем эти результаты из кэша в последующих запросах, вместо того, чтобы выполнять обратное обращение к базе данных.

Доступны и другие инструменты кэширования, такие как Memcached, который похож на Redis. Тем не менее, Redis более популярен, чем Memcached, потому что установка и работа в приложениях занимает всего несколько минут. Redis имеет более сложные механизмы, поскольку он был описан как «хранилище структуры данных», что делает его более мощным и гибким. Redis также имеет большее преимущество, потому что вы можете хранить данные в любой форме.

Надеемся, что это руководство показало вам, как легко добавить кеш-слой в ваше приложение, что повышает производительность. Кэширование должно быть чем-то, что нужно учитывать, когда вам нужно сократить время загрузки и затраты на сервер.