Trabajando con Redis en Python con Django

    Introducción

    Los datos se están convirtiendo cada vez más en un producto valioso en la era actual de la tecnología y esto requiere la optimización del almacenamiento y el acceso a estos datos.

    Existen bastantes soluciones notables para el almacenamiento de datos, incluidos los sistemas de gestión de bases de datos relacionales (RDBMS) como MySQL y PostgreSQL, que almacenan datos en un formato estructurado utilizando filas y columnas y las relaciones dentro de los datos.

    Además de RDBMS, existen almacenes de clave-valor que almacenan datos basados ​​en claves y valores únicos como un diccionario. Las bases de datos de valores clave pertenecen a la familia de bases de datos NoSQL que no se ajustan a la naturaleza relacional de RDBMS.

    En esta publicación, exploraremos Redis como almacén de valor clave y utilícelo en un proyecto para explorar su funcionalidad.

    ¿Qué es Redis y por qué usarlo?

    Redis (REmote DIctionary Server), es un almacén de estructura de datos en memoria que se puede utilizar como base de datos, caché o agente de mensajes.

    Los datos se almacenan en Redis en forma de pares clave-valor donde las claves se utilizan para ubicar y extraer los datos almacenados en la instancia de Redis.

    Las bases de datos normales almacenan datos en el disco, lo que genera un costo adicional, en términos de tiempo y recursos de hardware. Redis evita esto al almacenar todos los datos en la memoria, lo que hace que los datos estén fácilmente disponibles y aumenta la velocidad de acceso y manipulación de los datos, en comparación con las bases de datos normales.

    Esta es la razón por la que Redis es conocida por su excepcional capacidad de alto rendimiento.

    Redis nos permite almacenar datos en múltiples estructuras de datos de alto nivel, incluidas cadenas, hashes, listas, conjuntos y conjuntos ordenados. Esto nos da más flexibilidad sobre el tipo y la cantidad de información que podemos almacenar en un almacén de datos de Redis.

    Habiendo sido escrito en ANSI C, Redis es liviano y sin dependencias externas. También es bastante amigable para los desarrolladores, ya que admite la mayoría de lenguajes de alto nivel como Python, JavaScript, Java, C / C ++ y PHP.

    ¿Cuándo debería usar Redis?

    Los casos de uso comunes de Redis incluyen:

    • Almacenamiento en caché: Dada su velocidad sobre las bases de datos tradicionales, en términos de operaciones de lectura y escritura, Redis se ha convertido en una solución ideal para almacenar datos temporalmente en una caché para acelerar el acceso a los datos en el futuro.
    • Message Queue Server: Con la capacidad de implementar el paradigma de mensajería Publicar / Suscribirse, Redis se ha convertido en un agente de mensajes para sistemas de cola de mensajes.
    • Almacenamiento de datos: Redis se puede utilizar para almacenar datos de valor-clave como una base de datos NoSQL.

    Empresas como Twitter, Pinterest, Github, Snapchat y StackOverflow utilizan Redis para almacenar y hacer que los datos estén altamente disponibles para sus usuarios.

    Por ejemplo, Twitter almacena los tweets entrantes más recientes para un usuario en Redis para acelerar la entrega de los tweets a las aplicaciones del cliente.

    Pinterest usa Redis para almacenar una lista de usuarios y tableros que sigue un usuario, una lista de seguidores de un usuario y una lista de personas que siguen sus tableros, entre otras listas para mejorar la experiencia en la plataforma.

    Instalación de Redis

    Para explorar más a fondo Redis, necesitamos descargar e instalar el servidor de Redis siguiendo las instrucciones del página web oficial. Redis también está disponible como Imagen de Docker en Docker Hub.

    También se envía con una herramienta Redis-CLI que podemos usar para interactuar y manipular datos en nuestro servidor Redis.

    Redis también está disponible para su instalación a través de Homebrew (para MacOS) y a través del repositorio apt predeterminado para Debian Linux y sus variantes, como Ubuntu.

    Para instalar Redis en MacOS, simplemente ejecute:

    $ brew install redis
    

    En Debian Linux:

    $ sudo apt-get install redis-server
    

    Para verificar nuestra instalación de Redis, escriba el redis-cli comando, luego escriba ping en el mensaje que aparece:

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

    Podemos ver que nuestro servidor Redis está listo con la respuesta: PONG.

    Comandos de Redis

    Redis, a través de Redis-CLI, proporciona algunos comandos útiles que podemos usar para interactuar con el servidor Redis y manipular los datos almacenados allí. De forma predeterminada, los servidores de Redis se ejecutan en el puerto 6379 y esto será visible en nuestro mensaje.

    Los comandos disponibles dentro del indicador de Redis-CLI incluyen:

    • SET: Este comando se utiliza para establecer una clave y su valor, con parámetros opcionales adicionales para especificar el vencimiento de la entrada de clave-valor. Establezcamos una clave hello con el valor de world con una caducidad de 10 segundos:
    127.0.0.1:6379> SET hello "world" EX 10
    OK
    
    • GET: Este comando se usa para obtener el valor asociado con una clave. En caso de que la entrada de valor clave haya superado su período de vencimiento, nil Será devuelto:
    127.0.0.1:6379> GET hello
    “world”
    
    # After expiry
    127.0.0.1:6379> GET hello
    (nil)
    
    • DELETE: Este comando elimina una clave y el valor asociado:
    127.0.0.1:6379> DEL hello
    (integer) 1
    
    • TTL: Cuando una clave se configura con una caducidad, este comando se puede usar para ver cuánto tiempo queda:
    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
    
    • PERSIST: Si cambiamos de opinión sobre el vencimiento de una clave, podemos usar este comando para eliminar el período de vencimiento:
    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"
    
    • RENAME: Este comando se usa para cambiar el nombre de las claves en nuestro servidor 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"
    
    • FLUSHALL: Este comando se usa para purgar todas las entradas de valor-clave que hemos establecido en nuestra sesión actual:
    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)
    

    Puede encontrar más información sobre estos y otros comandos de Redis en el página web oficial.

    Redis con Django

    Para demostrar cómo integrar Redis en una aplicación web, crearemos una API usando Django y Django REST que puede recibir un par clave-valor y almacenarlo en nuestro servidor Redis.

    Nuestra API también podrá recuperar valores para claves determinadas, recuperar todos los pares clave-valor almacenados y también eliminar una entrada clave-valor.

    Empecemos creando una carpeta para albergar nuestro proyecto:

    $ mkdir redis_demo && cd $_
    

    Luego, creemos un entorno virtual y activámoslo:

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

    Y finalmente, instalemos las bibliotecas necesarias:

    $ pip install django djangorestframework redis
    

    La API de nuestra aplicación recibirá solicitudes e interactuará con nuestro servidor Redis utilizando el Redis-py biblioteca.

    Ahora creemos la aplicación:

    # 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
    

    Para verificar que nuestra configuración de Django fue exitosa, iniciamos el servidor:

    $ python manage.py runserver
    

    Cuando navegamos a http:127.0.0.1:8000, somos recibidos por:

    El siguiente paso es agregar nuestro api aplicación y Django REST a nuestro proyecto actualizando el INSTALLED_APPS lista encontrada en 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 necesita una instancia en ejecución de Redis para interactuar. Tendremos que configurar esto en nuestro django_redis_demo/settings.py añadiendo:

    REDIS_HOST = 'localhost'
    REDIS_PORT = 6379
    

    Con esta configuración, también podemos usar una instancia de Redis que se ejecuta dentro de un contenedor de Docker o una instancia de Redis remota, aunque es posible que debamos proporcionar detalles de autenticación para ese caso. Por ahora, usaremos nuestra instancia local de Redis que configuramos.

    A continuación, vamos a crear la ruta que se utilizará para acceder a nuestra API y vincularla a nuestra aplicación principal de Django. Primero, crearemos un vacío api/urls.py archivo, luego cree nuestra ruta en el django_redis_demo/urls.py:

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

    Todas las solicitudes que llegan a través del api/ el punto final ahora será manejado por nuestro api solicitud. Lo que falta ahora son las vistas que manejarán las solicitudes.

    Nuestras vistas serán vistas simples basadas en funciones que nos permitirán interactuar con el servidor Redis. Primero, creemos las URL con las que interactuaremos en nuestro 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('<slug:key>', manage_item, name="single_item")
    }
    urlpatterns = format_suffix_patterns(urlpatterns)
    

    La primera ruta nos permitirá crear entradas y ver todas las entradas, mientras que la segunda ruta nos dará una gestión granular de entradas individuales.

    Tendremos dos vistas basadas en funciones: manage_items() y manage_item() que manejará las solicitudes e interactuará con nuestra instancia de Redis. Ambos residirán en nuestro api/views.py archivo.

    Para explicar mejor el código, lo dividiremos en partes más concisas. Si desea ver el código completo, hay un enlace al repositorio de GitHub con el código fuente al final de este artículo.

    Comenzaremos importando las bibliotecas necesarias y conectándonos a nuestra instancia de 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)
    

    Aquí, creamos nuestro objeto de conexión pasando el host y el puerto de Redis como se configuró anteriormente en nuestro django_redis_demo/settings.py.

    Luego, creamos nuestra primera vista manage_items() que se utilizará para recuperar todos los elementos configurados actualmente en nuestra instancia de Redis en ejecución. Esta vista también nos permitirá crear nuevas entradas en nuestra instancia de Redis pasando un objeto 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)
    

    Entonces, definamos 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() nos da acceso a entradas individuales en nuestra instancia de Redis. Esta vista requiere que la persona que llama pase la clave del elemento que necesitamos en la URL.

    Esta clave luego se usa para ubicar el valor almacenado en nuestra instancia. Usando el PUT Método HTTP y pasando el nuevo valor de una clave, podemos actualizar el valor de la clave.

    A través de DELETE , podemos eliminar un par clave-valor de nuestra instancia de Redis.

    Para ver nuestra API en acción, usaremos Postman. Pero primero, creemos una entrada o dos usando el redis-cli herramienta:

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

    Después de configurar los datos, enviemos una solicitud GET a localhost:8000/api/items:

    Nuestra API puede recuperar todos los pares clave-valor en nuestra instancia actual de Redis. Ahora enviemos una solicitud POST con la siguiente carga útil a la misma URL:

    {
    "mighty": "mug"
    }
    

    Enviemos otra solicitud GET al mismo punto final:

    Podemos ver que la clave que creamos usando nuestra API se guarda en nuestra instancia de Redis. Podemos verificar su existencia utilizando la herramienta CLI.

    Probemos ahora el segundo punto final que devuelve el valor de una sola clave enviando una solicitud GET a http://localhost:8000/api/items/HELLO:

    Eso salió bien. Actualicemos ahora el valor asociado al HELLO clave enviando el siguiente JSON a través de una solicitud PUT al mismo punto final:

    {
    "new_value": "Pharos.sh.com"
    }
    

    Cuando buscamos la llave HELLO otra vez:

    Nuestro valor se ha actualizado con éxito. El último bit que queda es la eliminación de claves, así que sigamos adelante y enviemos un DELETE solicitud de http://localhost:8000/api/items/HELLO para eliminar la clave que acabamos de actualizar.

    Cuando intentamos acceder al mismo elemento después de eliminarlo:

    Se nos informa que nuestra clave ha sido eliminada. Nuestra API de Django se ha interconectado con éxito con nuestra instancia de Redis utilizando el Redis-py biblioteca.

    Conclusión

    Redis es una opción de almacenamiento de datos potente y rápida que, si se utiliza en la situación adecuada, puede aportar muchos beneficios. No tiene una curva de aprendizaje pronunciada, por lo que es fácil de aprender y también viene con una práctica herramienta CLI para ayudarnos a interactuar con él a través de comandos simples e intuitivos.

    Hemos podido integrar nuestra API de Django con una instancia de Redis que se ejecuta localmente sin problemas, lo que es un testimonio de su facilidad de uso con lenguajes de programación de alto nivel comunes.

    Se puede encontrar el código fuente del script en este proyecto. aquí en GitHub.

     

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *