Cómo almacenar en caché datos de MySQL con Redis y Node.js

Introducción

La principal ventaja de Node.js es manejar múltiples solicitudes colocándolas en una cola de eventos. Esta arquitectura basada en eventos hace que Node.js sea muy adecuado para codificar aplicaciones modernas en tiempo real. Aunque Node.js es rápido, puede mejorar su rendimiento de acceso a la base de datos utilizando un caché.

Existen muchas soluciones de almacenamiento en caché de bases de datos, pero esta guía se centra en Redis. Redis es un almacén de clave-valor que utiliza la memoria RAM de su computadora para el almacenamiento. La velocidad de transferencia de la RAM es varias veces más rápida que la de una unidad de estado sólido (SSD) típica.

Al acceder a las bases de datos con Node.js, debe usar el servidor Redis para almacenar en caché los resultados de las consultas de los datos a los que se accede con frecuencia. Por ejemplo, puede almacenar en caché productos en software de comercio electrónico, métodos de pago en aplicaciones de contabilidad o una lista de países en una base de datos de registro de clientes.

Esta guía le muestra cómo almacenar en caché datos de MySQL con Redis y Node.js en Ubuntu 20.04.

requisitos previos

Para seguir junto con esta guía:

  • Implemente un servidor Ubuntu 20.04.
  • Instale y asegure un servidor MySQL.
  • Instale la versión PPA de Node.js (Opción 2).
  • Instalar y configurar un servidor Redis.

1. Configurar una base de datos MySQL

El primer paso es configurar una base de datos para almacenar datos de forma permanente en un disco. Debido a que Redis utiliza la memoria RAM de la computadora para el almacenamiento de datos, no es adecuado para datos relacionales. Aunque Redis puede conservar los datos en el disco, no está diseñado para ese propósito y es posible que no funcione de manera óptima. Siga los pasos a continuación para crear una base de datos MySQL, una cuenta de usuario y una tabla de muestra:

  1. Inicie sesión en su servidor MySQL como root usuario.

                              
                                $ sudo mysql -u root -p
    
                              
                            
  2. Enter tu MySQL root contraseña y presione ENTER para continuar. Luego, emita los siguientes comandos SQL para crear una muestra e-commerce base de datos y una cuenta de usuario. Reemplazar EXAMPLE_PASSWORD con una contraseña segura.

                              
                                mysql> CREATE DATABASE e_commerce;
           CREATE USER 'e_commerce_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'EXAMPLE_PASSWORD';
           GRANT ALL PRIVILEGES ON e_commerce.* TO 'e_commerce_user'@'localhost';
           FLUSH PRIVILEGES;
    
                              
                            

    Producción.

                              
                                ...
    Query OK, 0 rows affected (0.01 sec)
    
                              
                            
  3. Cambiar a lo nuevo e_commerce base de datos.

                              
                                mysql> USE e_commerce;
    
                              
                            

    Producción.

                              
                                Database changed
    
                              
                            
  4. Crear un countries mesa. Esta tabla almacena una lista de países para su uso posterior en aplicaciones frontend. Por ejemplo, cuando los clientes se suscriben a sus servicios. Debe considerar el almacenamiento en caché de objetos que rara vez cambian, como países, métodos de pago y productos, para evitar entregar datos obsoletos a los usuarios de la interfaz.

                              
                                mysql> CREATE TABLE countries (
               country_id BIGINT NOT NULL PRIMARY KEY,
               country_name VARCHAR(100)
           ) ENGINE = InnoDB;
    
                              
                            

    Producción.

                              
                                Query OK, 0 rows affected (0.01 sec)
    
                              
                            
  5. Inserte datos de muestra en el countries mesa.

                              
                                mysql> INSERT INTO countries (country_id, country_name) values ('1', "USA");
           INSERT INTO countries (country_id, country_name) values ('39', "ITALY");
           INSERT INTO countries (country_id, country_name) values ('86', "CHINA");
           INSERT INTO countries (country_id, country_name) values ('81', "JAPAN");
           INSERT INTO countries (country_id, country_name) values ('27', "SOUTH AFRICA");
    
                              
                            

    Producción.

                              
                                ...
    Query OK, 1 row affected (0.01 sec)
    
                              
                            
  6. consulta el countries tabla para asegurarse de que los datos están en su lugar.

                              
                                mysql> SELECT
               country_id,
               country_name
           FROM countries;
    
                              
                            

    Producción.

                              
                                +------------+--------------+
    | country_id | country_name |
    +------------+--------------+
    |          1 | USA          |
    |         27 | SOUTH AFRICA |
    |         39 | ITALY        |
    |         81 | JAPAN        |
    |         86 | CHINA        |
    +------------+--------------+
    5 rows in set (0.01 sec)
    
                              
                            
  7. Cierre sesión en el servidor MySQL.

                              
                                mysql> QUIT;
    
                              
                            

    Producción.

                              
                                Bye
    
                              
                            

Después de configurar una base de datos, el siguiente paso se enfoca en crear un código Node.js que consulta la tabla de la base de datos para recuperar la lista de países. Más adelante, esta guía le muestra cómo almacenar en caché los resultados del servidor MySQL en un servidor Redis.

2. Crea un mysql_database Clase

Para mejorar la legibilidad del código y mejorar el soporte, debe crear un módulo separado para cada función en esta aplicación de muestra. El primer módulo que necesita es un mysql_database clase. Esta clase le permite conectarse a la base de datos MySQL y recuperar datos del countries tabla usando Node.js mysql módulo. Siga los pasos a continuación para crear la clase:

  1. Hacer una project directorio de su aplicación.

                              
                                $ mkdir project
    
                              
                            
  2. Navegar al nuevo project directorio.

                              
                                $ cd project
    
                              
                            
  3. abrir un nuevo mysql_database.js en un editor de texto.

                              
                                $ nano mysql_database.js
    
                              
                            
  4. Enter la siguiente información en el mysql_database.js expediente. Reemplazar EXAMPLE_PASSWORD con la contraseña correcta para el usuario de MySQL.

                              
                                class mysql_database {
    
        getData(callBack) {
    
            const mysql = require('mysql');
    
            const mysql_con = mysql.createConnection({
                host: "localhost",
                user: "e_commerce_user",
                password: "EXAMPLE_PASSWORD",
                database: "e_commerce"
             });
    
            mysql_con.connect(function(err) {
                if (err) {
                    console.log(err.message);
                }
            });
    
           var queryString = "select * from countries";
    
           mysql_con.query(queryString , [], function (err, result) {
               if (err) {
                   callBack(err, null);
               } else {
                   callBack(null, result);
               }
          });
    
        }
    }
    
    module.exports = mysql_database;
    
                              
                            
  5. Guardar y close la mysql_database.js archivo después de que haya terminado con la edición.

los mysql_database.js archivo explicado:

  1. los mysql_database.js El archivo encierra las operaciones de la base de datos en un mysql_database clase.

                              
                                class mysql_database {
        ...
    }
    
                              
                            
  2. los mysql_database la clase tiene un método. Eso es el getData(...) método.

                              
                                getData(callBack) {
        ...
    }
    
                              
                            
  3. los getData(...) El método toma las credenciales de la base de datos y crea una conexión a la base de datos usando el mysql.createConnection({...}) y connect(...) funciones

  4. los queryString variable almacena el comando SQL ( select * from countries ) que recupera registros de la countries mesa.

  5. Hacia el final, el getData(...) método asigna el result de la consulta de la base de datos a un callBack función para su posterior procesamiento. Más adelante, esta guía le muestra cómo codificar el callBack función.

  6. los module.exports = mysql_database; La línea al final del archivo indica a Node.js que haga que el módulo esté disponible en otros archivos de código fuente.

Su mysql_database la clase ya está lista. Puede importar esa clase en cualquier archivo de código fuente que requiera operaciones de base de datos usando el require('./mysql_database'); declaración.

3. Crea un redis_server Clase

Como el mysql_database clase, necesitas una separada redis_server class para conectarse a Redis que almacena y recupera valores clave.

  1. abrir un nuevo redis_server.js en un editor de texto.

                              
                                $ nano redis_server.js
    
                              
                            
  2. Enter la siguiente información en el archivo. Esta guía utiliza el host local ( 127.0.0.1 ) porque ha implementado Redis en su máquina local. Si desea acceder a un servidor Redis remoto, actualice este valor con la dirección IP pública correcta del host remoto. De forma predeterminada, el servidor Redis escucha las conexiones entrantes en el puerto 6379 .

                              
                                class redis_server {
    
        redisConnect() {
    
            const redis = require('redis');
    
            const redisClient = redis.createClient('127.0.0.1', 6379);
    
            redisClient.connect();
    
            redisClient.on('error', err => {
                console.log('Error ' + err);
            });
    
            return redisClient;
        }
    
        setData(data) {
            var redisClient = this.redisConnect();
            redisClient.set('countries', data);
        }
    
        getData(callBack) {
            var redisClient = this.redisConnect();
            var resp = redisClient.get('countries');
    
            resp.then(function(result) {
                callBack(null, result)
            });
        }
    }
    
    module.exports = redis_server;
    
                              
                            
  3. Guardar y close la redis_server.js cuando haya terminado con la edición.

los redis_server.js archivo explicado:

  1. los redis_server.js el archivo contiene uno redis_server clase.

                              
                                class redis_server {
        ...
    }
    
                              
                            
  2. los redis_server la clase alberga tres métodos:

    • redisConnect(){...} : Este método importa el redis módulo y se conecta al servidor Redis usando el redis.createClient(...) y redisClient.connect() funciones

    • setData(data){...} : Este método acepta un data Argumento de cadena que contiene los resultados de la base de datos MySQL. los setData(data){...} El método luego usa la conexión Redis ( this.redisConnect(...) ) para guardar datos en el servidor Redis usando el redisClient.set('countries', data) declaración. los countries variable es el nombre de la clave Redis que almacena los datos en el servidor Redis.

    • getData(callBack){} : Esta función se conecta al servidor Redis ( this.redisConnect() ) y utiliza Redis redisClient.get('countries') función para recuperar el valor de la countries llave.

  3. los module.exports = redis_server; declaración al final del archivo le permite exponer e importar el redis_server funciones en otros archivos de código fuente.

los redis_server el módulo ya está listo. Puede importarlo a otros archivos de código fuente usando el require('./redis_server'); declaración.

4. Crea un main.js Expediente

El último archivo que necesita para este proyecto es el main.js expediente. Este archivo se ejecuta cuando ejecuta la aplicación. los main.js El archivo es un punto de entrada a su aplicación. Siga los pasos a continuación para crear el archivo:

  1. abrir un nuevo main.js archivo en un editor de texto.

                              
                                $ nano main.js
    
                              
                            
  2. Enter la siguiente información en el main.js expediente.

                              
                                const mysql_database = require('./mysql_database');
    const redis_server = require('./redis_server');
    
    const http = require('http');
    const hostname="127.0.0.1";
    const port = 8080;
    
    const server = http.createServer(httpHandler);
    
    server.listen(port, hostname, () => {
        console.log(`Server running at https://${hostname}:${port}/`);
    });
    
    function httpHandler(req, res) {
    
        const mysqlDatabase = new mysql_database();
        const redisServer = new redis_server();
    
        redisServer.getData( (redisErr, redisResult) => {
    
            if (redisErr) {
                console.log(redisErr.message);
            } else {
    
                if (redisResult == null )  {
    
                    mysqlDatabase.getData((mysqlErr, mysqlResult) => {
    
                        jsonData = JSON.stringify(mysqlResult, null, 4)
                        redisServer.setData(jsonData);
    
                        var countries = {_source:'MySQL Server', data: JSON.parse(jsonData)};
    
                        res.write(JSON.stringify(countries, null, 4));
                        res.end();
                    });
    
                } else {
    
                    var countries = {_source:'Redis Server', data: JSON.parse(redisResult)};
    
                    res.write(JSON.stringify(countries, null, 4));
                    res.end();
                }
        }
    
        });
    
    
    }
    
                              
                            
  3. Guardar y close la main.js expediente.

los main.js archivo explicado:

  1. Las dos primeras líneas en la parte superior del archivo importan el mysql_database y redis_server módulos que creó anteriormente.

                              
                                ...
    const mysql_database = require('./mysql_database');
    const redis_server = require('./redis_server');
    ...
    
                              
                            
  2. Las siguientes líneas importan el http módulo servidor. El módulo le permite ejecutar el servidor HTTP incorporado de Node.js en la aplicación. El servidor HTTP escucha las conexiones entrantes en el puerto 8080 . A continuación, ha utilizado el http.createServer(httpHandler); línea para instruir al http módulo para reenviar solicitudes HTTP a un httpHandler(...) función.

                              
                                ...
    const http = require('http');
    const hostname="127.0.0.1";
    const port = 8080;
    
    const server = http.createServer(httpHandler);
    
    server.listen(port, hostname, () => {
        console.log(`Server running at https://${hostname}:${port}/`);
    });
    ...
    
                              
                            
  3. los httpHandler(req, res) {...}) La función se ejecuta cuando su aplicación recibe una solicitud HTTP.

                              
                                ...
    function httpHandler(req, res) {
        ...
    }
    ...
    
                              
                            
  4. Bajo la httpHandler(req, res) {...}) función, está creando instancias de MySQL ( mysql_database ) y Redis ( redis_server ) módulos de base de datos que codificó anteriormente usando las siguientes declaraciones.

                              
                                ...
    const mysqlDatabase = new mysql_database();
    const redisServer = new redis_server();
    ...
    
                              
                            
  5. los redisServer.getData(..){..} La función luego consulta el servidor Redis para verificar si hay un valor en el countries llave.

                              
                                ...
    redisServer.getData( (redisErr, redisResult) => {
        ...
    }
    ...
    
                              
                            
  6. La declaración lógica if (redisResult == null ) {...} declaración examina más a fondo el resultado de Redis para comprobar si Redis devuelve un null valor. A null El valor significa que el servidor Redis no tiene una copia de los resultados de MySQL. En tal situación, la aplicación consulta la base de datos MySQL ( mysqlDatabase.getData(...) ), devuelve el valor en formato JSON y almacena en caché los datos en el servidor Redis ( redisServer.setData(jsonData); ). Si el servidor Redis ya ha almacenado en caché los datos, devuelve el resultado.

                              
                                ...
            if (redisErr) {
                console.log(redisErr.message);
            } else {
    
                if (redisResult == null )  {
    
                    mysqlDatabase.getData((mysqlErr, mysqlResult) => {
    
                        jsonData = JSON.stringify(mysqlResult, null, 4)
                        redisServer.setData(jsonData);
    
                        var countries = {_source:'MySQL Server', data: JSON.parse(jsonData)};
    
                        res.write(JSON.stringify(countries, null, 4));
                        res.end();
                    });
    
                } else {
    
                    var countries = {_source:'Redis Server', data: JSON.parse(redisResult)};
    
                    res.write(JSON.stringify(countries, null, 4));
                    res.end();
                }
        }
    ...
    
                              
                            
  7. los JSON.stringify(mysqlResult, null, 4) La función convierte los datos en una cadena JSON cuando los pasa a Redis. La función también muestra una buena salida JSON a la función de llamada.

Ya ha codificado todos los módulos necesarios y ha creado un main.js archivo para su aplicación. El siguiente paso es probar la aplicación.

5. Pruebe la aplicación

Su aplicación ahora está lista para ser probada. Este paso se enfoca en importar los módulos que usó en esta aplicación, inicializar el directorio de su paquete y ejecutar pruebas usando Linux curl dominio.

  1. Inicialice su aplicación project directorio.

                              
                                $ npm init
    
                              
                            

    Responde con la siguiente información:

                              
                                package name: (project) redis-cache ENTER
    version: (1.0.0) 1.0.0 ENTER
    description: Redis cache with Node.js and MySQL ENTER
    entry point: (main.js) main.js ENTER
    test command: ENTER
    git repository: ENTER
    keywords: redis, cache, mysql ENTER
    author: test author ENTER
    license: (ISC) ENTER
    ...
    Is this OK? (yes) yes ENTER
    
                              
                            

    Producción.

                              
                                npm notice
    npm notice New minor version of npm available! 8.11.0 -> 8.15.1
    npm notice Changelog: https://github.com/npm/cli/releases/tag/v8.15.1
    npm notice Run npm install -g [email protected] to update!
    npm notice
    
                              
                            

    Ignora el npm aviso por ahora. Su aplicación debería funcionar bien con el instalado npm versión.

  2. Use el administrador de paquetes de Node.js ( npm ) para descargar el mysql y redis módulos.

                              
                                $ npm install mysql
    $ npm install redis
    
                              
                            

    Producción.

                              
                                added 11 packages, and audited 12 packages in 2s
    found 0 vulnerabilities
    ...
    added 10 packages, and audited 22 packages in 4s
    found 0 vulnerabilities
    
                              
                            
  3. Utilizar el node comando para ejecutar la aplicación. Ese comando tiene una función de bloqueo. No ingrese ningún otro comando en su ventana de terminal activa.

                              
                                $ node main.js
    
                              
                            

    Su aplicación activa un servidor web y muestra el siguiente resultado.

                              
                                Server running at https://127.0.0.1:8080/
    
                              
                            
  4. Conéctese a su servidor Ubuntu en otra ventana de terminal y ejecute lo siguiente curl comando para enviar un GET petición a la aplicación.

                              
                                $ curl -X GET https://localhost:8080
    
                              
                            
  5. Compruebe el valor de la _source atributo ( MySQL Server ). Debido a que ha ejecutado la aplicación por primera vez, la aplicación devuelve datos directamente desde el servidor MySQL.

                              
                                {
        "_source": "MySQL Server",
        "data": [
            {
                "country_id": 1,
                "country_name": "USA"
            },
            {
                "country_id": 27,
                "country_name": "SOUTH AFRICA"
            },
            {
                "country_id": 39,
                "country_name": "ITALY"
            },
            {
                "country_id": 81,
                "country_name": "JAPAN"
            },
            {
                "country_id": 86,
                "country_name": "CHINA"
            }
        ]
    }
    
                              
                            
  6. Repite el curl dominio. Esta vez, el _source el valor del atributo cambia a Redis Server . El resultado muestra que su aplicación ha almacenado en caché con éxito los datos de MySQL en el servidor de Redis y la aplicación ahora atiende todas las solicitudes de Redis.

                              
                                {
        "_source": "Redis Server",
        "data": [
            {
                "country_id": 1,
                "country_name": "USA"
            },
            {
                "country_id": 27,
                "country_name": "SOUTH AFRICA"
            },
            {
                "country_id": 39,
                "country_name": "ITALY"
            },
            {
                "country_id": 81,
                "country_name": "JAPAN"
            },
            {
                "country_id": 86,
                "country_name": "CHINA"
            }
        ]
    }
    
                              
                            

Su aplicación está funcionando como se esperaba.

Conclusión

Esta guía demuestra la idea de almacenar en caché datos MySQL con Redis en una aplicación Node.js. Aunque esta guía almacena en caché una sola tabla de base de datos MySQL, puede extender el código fuente para almacenar en caché otros objetos según el caso de uso de su aplicación. Sin embargo, evite servir datos obsoletos estableciendo una política de invalidación de caché. Una buena política debería ayudarlo a invalidar las claves Redis después de actualizar los valores base en el servidor MySQL.

Título del artículo Nombre (opcional) Correo electrónico (opcional) Descripción

Enviar sugerencia

Related Posts