Рубрики
Без рубрики

Работа с Redis на Python с Django

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

Автор оригинала: Robley Gori.

Работа с Redis на Python с Django

Вступление

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

Существует довольно много известных решений для хранения данных, включая Реляционные системы управления базами данных (СУБД), такие как MySQL и PostgreSQL , которые хранят данные в структурированном формате с использованием строк и столбцов и отношений внутри данных.

Помимо СУБД, существуют хранилища ключ-значение, которые хранят данные на основе уникальных ключей и значений, таких как словарь. Базы данных ключ-значение относятся к семейству баз данных NoSQL , которые не соответствуют реляционной природе СУБД.

В этом посте мы рассмотрим Redis как хранилище ключевых значений и используем его в проекте для изучения его функциональности.

Что такое Redis и зачем его использовать?

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

Данные хранятся в Redis в виде key-values , где ключи используются для поиска и извлечения данных, хранящихся в экземпляре Redis.

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

Именно по этой причине Redis известен своими исключительными высокопроизводительными возможностями.

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

Будучи написанным на языке ANSI C , Redis является легким и не имеет внешних зависимостей. Он также довольно дружелюбен к разработчикам, так как поддерживает большинство языков высокого уровня, таких как Python, JavaScript, Java, C/C++ и PHP.

Когда вы должны использовать Redis?

Общие случаи использования Redis включают в себя:

  • Кэширование : Учитывая его скорость по сравнению с традиционными базами данных, с точки зрения операций чтения и записи, Redis стал идеальным решением для временного хранения данных в кэше для ускорения доступа к данным в будущем.
  • Очередь сообщений : Благодаря возможности реализации парадигмы обмена сообщениями Publish/Subscribe Redis стала брокером сообщений для систем очереди сообщений.
  • Хранение данных : Redis можно использовать для хранения данных ключ-значение в виде базы данных NoSQL.

Такие компании, как Twitter, Pinterest, Github, Snapchat и StackOverflow, используют Redis для хранения и обеспечения высокой доступности данных для своих пользователей.

Например, Twitter хранит самые последние входящие твиты для пользователя на Reddit, чтобы ускорить доставку твитов в клиентские приложения.

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

Установка Redis

Для дальнейшего изучения Redis нам необходимо загрузить и установить сервер Redis, используя инструкции с официального сайта . Redis также доступен в виде образа Docker на Docker Hub .

Он также поставляется с инструментом Redis-CLI , который мы можем использовать для взаимодействия с данными на нашем сервере Redis и манипулирования ими.

Redis также доступен для установки через Homebrew (для Mac OS) и через репозиторий apt по умолчанию для Debian Linux и его вариантов, таких как Ubuntu.

Чтобы установить Redis на Mac OS, просто запустите:

$ brew install redis

В Debian Linux:

$ sudo apt-get install redis-server

Чтобы проверить установку Redis, введите команду redis-cli , а затем введите ping в появившемся приглашении:

$ redis-cli -v
redis-cli 5.0.6
$ redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>

Мы видим, что наш сервер Redis готов к ответу – PONG .

Команды Redis

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

Команды, доступные в командной строке Redis-CLI, включают:

  1. SET : Эта команда используется для установки ключа и его значения с дополнительными необязательными параметрами для указания срока действия записи ключ-значение. Давайте установим ключ hello со значением world с истечением 10 секунд:
127.0.0.1:6379> SET hello "world" EX 10
OK
  1. GET : Эта команда используется для получения значения, связанного с ключом. В случае, если запись ключ-значение превысила свой срок действия, будет возвращен nil :
127.0.0.1:6379> GET hello
"world"

# After expiry
127.0.0.1:6379> GET hello
(nil)
  1. DELETE : Эта команда удаляет ключ и связанное с ним значение:
127.0.0.1:6379> DEL hello
(integer) 1
  1. TTL : Когда ключ установлен с истечением срока действия, эта команда может быть использована для просмотра того, сколько времени осталось:
127.0.0.1:6379> SET foo "bar" EX 100     # 100 is the number of seconds
OK

127.0.0.1:6379> TTL foo
(integer) 97      # Number of seconds remaining till expiry

127.0.0.1:6379> TTL foo
(integer) 95

127.0.0.1:6379> TTL foo
(integer) 93
  1. PERSIST : Если мы изменим свое мнение об истечении срока действия ключа, мы можем использовать эту команду для удаления срока действия:
127.0.0.1:6379> PERSIST foo
(integer) 1

127.0.0.1:6379> TTL foo
(integer) -1

127.0.0.1:6379> GET foo
"bar"
  1. RENAME : Эта команда используется для переименования ключей на нашем сервере Redis:
127.0.0.1:6379> RENAME foo foo2
OK

127.0.0.1:6379> GET foo
(nil)

127.0.0.1:6379> GET foo2
"bar"
  1. FLUSH ALL : Эта команда используется для очистки всех записей ключ-значение, которые мы установили в нашем текущем сеансе:
127.0.0.1:6379> RENAME foo foo2
OK

127.0.0.1:6379> GET foo
(nil)

127.0.0.1:6379> GET foo2
(nil)

127.0.0.1:6379> GET hello
(nil)

Более подробную информацию об этих и других командах Redis можно найти на официальном сайте .

Редис с Джанго

Чтобы продемонстрировать, как интегрировать Redis в веб-приложение, мы создадим API с использованием Django и Django REST, который может получать пару ключ-значение и хранить ее на нашем сервере Redis.

Наш API также сможет извлекать значения для заданных ключей, извлекать все сохраненные пары ключ-значение, а также удалять запись ключ-значение.

Давайте начнем с создания папки для размещения нашего проекта:

$ mkdir redis_demo && cd $_

Затем давайте создадим виртуальную среду и активируем ее:

$ virtualenv --python=python3 env --no-site-packages
$ source env/bin/activate

И, наконец, давайте установим необходимые библиотеки:

$ pip install django djangorestframework redis

API нашего приложения будет получать запросы и взаимодействовать с нашим сервером Redis с помощью библиотеки Redis-py .

Теперь давайте создадим приложение:

# Create the project
$ django-admin startproject django_redis_demo
$ cd django_redis_demo

# Create the app
$ django-admin startapp api

# Migrate
$ python manage.py migrate

Чтобы убедиться, что ваша настройка Django прошла успешно, мы запускаем сервер:

$ python manage.py runserver

Когда мы переходим к http:127.0.0.1:8000 , мы приветствованы:

настройка django

Следующий шаг-добавить ваше api приложение и Django REST в наш проект, обновив список INSTALLED_APPS , найденный в django_redis_demo/settings.py :

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Add these two
    'rest_framework',
    'api',
]

Redis-py нуждается в работающем экземпляре Redis для взаимодействия. Нам придется настроить это в нашем django_redis_demo/settings.py путем добавления:

REDIS_HOST = 'localhost'
REDIS_PORT = 6379

С помощью этого параметра мы также можем использовать экземпляр Redis, работающий внутри контейнера Docker, или удаленный экземпляр Redis, даже если для этого случая нам может потребоваться предоставить данные аутентификации. На данный момент мы будем использовать наш локальный экземпляр Redis, который мы создали.

Далее мы создадим маршрут, который будет использоваться для доступа к нашему API, и свяжем его с нашим основным приложением Django. Во-первых, мы создадим пустой api/urls.py файл, затем создайте наш путь в django_redis_demo/urls.py :

# Modify this import
from django.urls import path, include

urlpatterns = [
    ...
    # Add this entry
    path('api/', include('api.urls')),
]

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

Наши представления будут простыми функциональными представлениями, которые позволят нам взаимодействовать с сервером Redis. Во-первых, давайте создадим URL-адреса, с которыми мы будем взаимодействовать в нашем api/urls.py :

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from .views import manage_items, manage_item

urlpatterns = {
    path('', manage_items, name="items"),
    path('', manage_item, name="single_item")
}
urlpatterns = format_suffix_patterns(urlpatterns)

Первый путь позволит нам создавать записи и просматривать все записи, в то время как второй путь даст нам детальное управление отдельными записями.

У нас будет два представления на основе функций: manage_items() и manage_item () , которые будут обрабатывать запросы и взаимодействовать с нашим экземпляром Redis. Они оба будут проживать в нашем api/views.py файл.

Чтобы лучше объяснить код, мы разберем его на более сжатые куски. Если вы хотите увидеть полный код, в конце этой статьи есть ссылка на репозиторий GitHub с исходным кодом.

Мы начнем с импорта необходимых библиотек и подключения к вашему экземпляру Redis:

import json
from django.conf import settings
import redis
from rest_framework.decorators import api_view
from rest_framework import status
from rest_framework.response import Response

# Connect to our Redis instance
redis_instance = redis.StrictRedis(host=settings.REDIS_HOST,
                                  port=settings.REDIS_PORT, db=0)

Здесь мы создаем наш объект подключения, передавая хост Redis и порт, как ранее было настроено в вашем django_redis_demo/settings.py .

Затем мы создаем наше первое представление manage_items () , которое будет использоваться для извлечения всех элементов, установленных в данный момент в нашем запущенном экземпляре Redis. Это представление также позволит нам создавать новые записи в нашем экземпляре Redis, передавая объект JSON:

@api_view(['GET', 'POST'])
def manage_items(request, *args, **kwargs):
    if request.method == 'GET':
        items = {}
        count = 0
        for key in redis_instance.keys("*"):
            items[key.decode("utf-8")] = redis_instance.get(key)
            count += 1
        response = {
            'count': count,
            'msg': f"Found {count} items.",
            'items': items
        }
        return Response(response, status=200)
    elif request.method == 'POST':
        item = json.loads(request.body)
        key = list(item.keys())[0]
        value = item[key]
        redis_instance.set(key, value)
        response = {
            'msg': f"{key} successfully set to {value}"
        }
        return Response(response, 201)

Затем давайте определим manage_item() :

@api_view(['GET', 'PUT', 'DELETE'])
def manage_item(request, *args, **kwargs):
    if request.method == 'GET':
        if kwargs['key']:
            value = redis_instance.get(kwargs['key'])
            if value:
                response = {
                    'key': kwargs['key'],
                    'value': value,
                    'msg': 'success'
                }
                return Response(response, status=200)
            else:
                response = {
                    'key': kwargs['key'],
                    'value': None,
                    'msg': 'Not found'
                }
                return Response(response, status=404)
    elif request.method == 'PUT':
        if kwargs['key']:
            request_data = json.loads(request.body)
            new_value = request_data['new_value']
            value = redis_instance.get(kwargs['key'])
            if value:
                redis_instance.set(kwargs['key'], new_value)
                response = {
                    'key': kwargs['key'],
                    'value': value,
                    'msg': f"Successfully updated {kwargs['key']}"
                }
                return Response(response, status=200)
            else:
                response = {
                    'key': kwargs['key'],
                    'value': None,
                    'msg': 'Not found'
                }
                return Response(response, status=404)

    elif request.method == 'DELETE':
        if kwargs['key']:
            result = redis_instance.delete(kwargs['key'])
            if result == 1:
                response = {
                    'msg': f"{kwargs['key']} successfully deleted"
                }
                return Response(response, status=404)
            else:
                response = {
                    'key': kwargs['key'],
                    'value': None,
                    'msg': 'Not found'
                }
                return Response(response, status=404)

manage_item() дает нам доступ к отдельным записям в нашем экземпляре Redis. Это представление требует, чтобы вызывающий объект передал ключ нужного нам элемента в URL-адресе.

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

С помощью метода DELETE мы можем удалить пару ключ-значение из нашего экземпляра Redis.

Чтобы увидеть наш API в действии, мы будем использовать Postman . Но сначала давайте создадим одну или две записи с помощью инструмента redis-cli :

$ redis-cli
127.0.0.1:6379> SET HELLO "WORLD"
OK
127.0.0.1:6379> SET REDIS "DEMO"
OK

После установки данных отправим запрос GET на localhost:8000/api/items :

получить все предметы

Наш API способен извлекать все пары ключ-значение в нашем текущем экземпляре Redis. Теперь давайте отправим POST запрос со следующей полезной нагрузкой на тот же URL:

{
"mighty": "mug"
}

Давайте отправим еще один запрос GET на ту же конечную точку:

получить все элементы после обновления

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

Давайте теперь проверим вторую конечную точку, которая возвращает значение одного ключа, отправив запрос GET в http://localhost:8000/api/items/HELLO :

получить один предмет

Все прошло хорошо. Давайте теперь обновим значение, связанное с ключом HELLO , отправив следующий JSON через запрос PUT в ту же конечную точку:

{
"new_value": "stackabuse.com"
}

Когда мы принесем ключ ПРИВЕТ снова:

обновление одного элемента

Наша ценность была успешно обновлена. Последний оставшийся бит-это удаление ключей, поэтому давайте продолжим и отправим запрос DELETE в http://localhost:8000/api/items/HELLO чтобы удалить ключ, который мы только что обновили.

Когда мы пытаемся получить доступ к одному и тому же элементу после его удаления:

сообщение об удалении одного элемента

Нам сообщили, что наш ключ был удален. Наш API Django успешно взаимодействует с нашим экземпляром Redis с помощью библиотеки Redis-py .

Вывод

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

Мы смогли легко интегрировать наш API Django с локально запущенным экземпляром Redis, что является свидетельством его простоты использования с обычными языками программирования высокого уровня.

Исходный код скрипта в этом проекте можно найти здесь, на GitHub .