Using Redis® Queues for Sequential Job Processing in PHP

The Redis® queue library enables you to manage a sequential stream of jobs processed in a first-come, first-served order. This method is particularly useful in web development when you need to prevent users from waiting while the system performs time-consuming tasks. For example, in a high-traffic e-commerce platform, operations like payment validation and address checks can be handled in the background using queues and worker processes. In simple terms, if your application needs to maintain order in task execution but can’t afford to delay user interaction, implementing a Redis® queue—such as for a file conversion system—can be a practical solution.

This walkthrough explains how to leverage Redis® commands RPUSH and LPOP alongside PHP and MySQL to manage user sign-ups within a MySQL database on an Ubuntu 20.04 server.

System Requirements

Before you begin, ensure you have the following resources ready:

  • An Ubuntu 20.04-based server
  • User access with sudo privileges
  • A complete LAMP (Linux, Apache, MySQL, PHP) setup
  • An active Redis® server

Installing the php-redis Module

Start by accessing your server. Next, update your system’s package index and install the php-redis package. This module enables integration of Redis® features within your PHP scripts.

$ sudo apt update
$ sudo apt install -y php-redis

After installing the module, restart the Apache service to make the new configurations take effect.


$ sudo systemctl restart apache2


Setting Up the test_db Database

In this section of the tutorial, you’ll temporarily store customer sign-up data in Redis®, and later transfer it to a MySQL database for long-term storage.

Begin by accessing your MySQL server using the root account:

After entering your MySQL root password and hitting Enter, create a new database named test_db:

mysql> CREATE DATABASE test_db;

Next, define a MySQL user called test_db_user and assign a strong password (replace EXAMPLE_PASSWORD with your actual value). This user will be used to interact with MySQL from your PHP application.

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

If you’re using MariaDB instead of MySQL, you should modify the user creation step as follows:

MariaDB> GRANT ALL PRIVILEGES on test_db.* TO 'test_db_user'@'localhost' identified by 'EXAMPLE_PASSWORD';

Now, switch the active database context to test_db using the command below:

Proceed to create a customers table using this SQL command:

mysql> CREATE TABLE customers (
       customer_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
       first_name VARCHAR(50),
       last_name VARCHAR(50),
       email_address VARCHAR(255)
       ) ENGINE = InnoDB;

Do not insert any records into the customers table just yet. You will fill it later using a worker that retrieves data from Redis®. When finished, exit the MySQL interface:


Creating the PHP Script for Redis® Queue

To start, create a new PHP file named redis_queue.php in your web server’s root directory using nano. This script will collect customer details through POST requests and add them to the Redis® queue.

$ sudo nano /var/www/html/redis_queue.php

Insert the following content into the file:

<?php
    try {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);

        $data = [];
        $data = [
            'first_name'    => $_POST['first_name'],
            'last_name'     => $_POST['last_name'],
            'email_address' => $_POST['email_address']
        ];

        $redis->rpush("customers_register", json_encode($data));

        echo "Customer details accepted successfully.\n";

    } catch (Exception $e) {
        echo $e->getMessage();
    }

This script connects to the Redis® server on localhost via port 6379. It collects the customer’s submitted data from the $_POST array and structures it into an associative array. The array is then encoded into JSON and added to the Redis® list named customers_register using the rpush method. A confirmation message is displayed upon successful queuing of the data.

Submitting Customer Records to the Redis® Queue

Typically, users would enter their details using HTML forms. However, for this tutorial, you’ll use the curl command-line tool to simulate user data submission directly to http://localhost/redis_queue.php.

Execute the following commands one at a time to queue three separate customer records:

$ curl --data "first_name=JOHN&last_name=DOE&email_address=john_doe@example.com" http://localhost/redis_queue.php
$ curl --data "first_name=MARY&last_name=SMITH&email_address=mary_smith@example.com" http://localhost/redis_queue.php
$ curl --data "first_name=ROE&last_name=STEVE&email_address=roe_steve@example.com" http://localhost/redis_queue.php

Each command should return the following message as confirmation:

Customer details accepted successfully.

This output verifies that the customer data was successfully queued by the Redis® server. In the next step, you’ll develop a background worker to process these entries.

Building a PHP Script for Redis® Queue

To begin, create a new PHP file called redis_queue.php inside your server’s root directory. This script will handle POST requests containing customer registration details.

$ sudo nano /var/www/html/redis_queue.php

Now insert the following PHP code into the file:

<?php
    try {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);

        $data = [];
        $data = [
            'first_name'    => $_POST['first_name'],
            'last_name'     => $_POST['last_name'],
            'email_address' => $_POST['email_address']
        ];

        $redis->rpush("customers_register", json_encode($data));

        echo "Customer details accepted successfully.\n";

    } catch (Exception $e) {
        echo $e->getMessage();
    }

This script establishes a connection to the Redis® instance running locally on port 6379. It then retrieves input data from the $_POST array and organizes it into an associative array called $data. After encoding this array into a JSON string, the script pushes it to the customers_register list in Redis® using the rpush method. If successful, the script outputs a confirmation message.

Submitting Customer Data to the Queue

Although HTML forms would typically handle user registration in a live environment, for this tutorial, you’ll use the curl command to simulate form submissions. The data will be sent to the redis_queue.php script located at http://localhost/redis_queue.php.

Execute the following commands individually to queue three different customer records:

$ curl --data "first_name=JOHN&last_name=DOE&email_address=john_doe@example.com" http://localhost/redis_queue.php
$ curl --data "first_name=MARY&last_name=SMITH&email_address=mary_smith@example.com" http://localhost/redis_queue.php
$ curl --data "first_name=ROE&last_name=STEVE&email_address=roe_steve@example.com" http://localhost/redis_queue.php

Each command should generate the following output:

Customer details accepted successfully.

This confirmation message indicates that the Redis® queue is successfully receiving and storing the customer data. Next, you’ll implement a worker to process the entries in the queue.

Persisting Redis® Data to a MySQL Database

Now you’ll create a background process that removes customer entries from the Redis® queue and stores them permanently in a MySQL database. This will be achieved using Redis®’s LPOP function, which follows the FIFO (First-In, First-Out) model.

Start by creating a new PHP file named redis_worker.php in the root directory of your web server:

$ sudo nano /var/www/html/redis_worker.php

Add the following PHP code into the file:

<?php
    try {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);

        $data = $redis->lpop('customers_register');
        $data = json_decode($data, true);

        if (!empty($data)) {
            $db_name     = 'test_db';
            $db_user     = 'test_db_user';
            $db_password = 'EXAMPLE_PASSWORD';
            $db_host     = 'localhost';

            $pdo = new PDO('mysql:host=' . $db_host . '; dbname=' . $db_name, $db_user, $db_password);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

            $sql = 'insert into customers
                    (
                    first_name,
                    last_name,
                    email_address
                    )
                    values
                    (
                    :first_name,
                    :last_name,
                    :email_address
                    )';

            $stmt = $pdo->prepare($sql);
            $stmt->execute($data);

            echo $data['first_name'] . " " . $data['last_name'] . "'s details saved to database.";
        }

    } catch (Exception $e) {
        echo $e->getMessage();
    }

This script establishes a connection with the local Redis® instance and retrieves the oldest customer entry from the customers_register queue using the lpop method. The data, initially encoded as JSON, is decoded into an array and inserted into the customers table using PHP Data Objects (PDO).

The SQL insert statement utilizes bound parameters, which is a recommended practice to defend against SQL injection threats. Upon successful insertion, the script displays a message indicating that the customer’s details were stored in the database.

Please note: This implementation is for demonstration purposes and does not include any form of input validation. For real-world applications, make sure to add data sanitation and security checks to strengthen the integrity of your system.

Validating the Redis® Worker Script

To verify that the redis_worker.php script is functioning properly, you’ll need to access the URL http://localhost/redis_worker.php. Run the following command three times to process all previously queued entries:

$ curl http://localhost/redis_worker.php

If everything is set up correctly, the output should indicate that customer records are being removed from the Redis® list and stored in the database in the same order they were added:

JOHN DOE's details saved to database.
MARY SMITH's details saved to database.
ROE STEVE's details saved to database.

Checking the Data in the MySQL Database

To confirm that all customer data has been correctly stored, log into your MySQL server using the root user credentials:

Once authenticated, select the appropriate database:

Now run a SELECT query to display all entries in the customers table:

mysql> SELECT
       customer_id,
       first_name,
       last_name,
       email_address
       FROM customers;

If successful, the output should resemble the table below, indicating that the Redis® queuing and processing system is functioning correctly:

+-------------+------------+-----------+------------------------+
| customer_id | first_name | last_name | email_address          |
+-------------+------------+-----------+------------------------+
|           1 | JOHN       | DOE       | john_doe@example.com   |
|           2 | MARY       | SMITH     | mary_smith@example.com |
|           3 | ROE        | STEVE     | roe_steve@example.com  |
+-------------+------------+-----------+------------------------+
3 rows in set (0.00 sec)

When finished, exit the MySQL command-line session:


Automating the Redis® Worker with a Cron Job

Previously, you executed the redis_worker.php script manually using the curl command. In this step, you’ll automate that process by configuring a cron job to run the worker at regular intervals without manual intervention.

Start by opening the system’s crontab file:

Append the following line at the bottom of the file to run the redis_worker.php script every minute:

* * * * * root /usr/bin/wget -O - http://localhost/redis_worker.php

Save and exit the crontab file. Then, send a new customer entry to the redis_queue.php endpoint:

$ curl --data "first_name=BABY&last_name=SMALL&email_address=baby_small@example.com" http://localhost/redis_queue.php

The command should return a success message confirming that the customer data was added to the Redis® queue:

Customer details accepted successfully.

Wait approximately one minute, then log in to your MySQL database to verify the data was processed:

Once inside the MySQL CLI, switch to the appropriate database:

Then, check the customers table using the following query:

mysql> SELECT
       customer_id,
       first_name,
       last_name,
       email_address
       FROM customers;

If everything is working, you should see the new entry in the list:

+-------------+------------+-----------+------------------------+
| customer_id | first_name | last_name | email_address          |
+-------------+------------+-----------+------------------------+
|           1 | JOHN       | DOE       | john_doe@example.com   |
|           2 | MARY       | SMITH     | mary_smith@example.com |
|           3 | ROE        | STEVE     | roe_steve@example.com  |
|           4 | BABY       | SMALL     | baby_small@example.com |
+-------------+------------+-----------+------------------------+
4 rows in set (0.00 sec)

For critical systems where one-minute intervals are not sufficient, consider creating a long-running PHP loop that continuously polls for new data.

Conclusion

This tutorial has demonstrated how to implement job queuing using Redis® and PHP on an Ubuntu 20.04 server. You’ve learned how to push data into a Redis® queue, process it with a background worker, and permanently store the data in a MySQL database. You can adapt and expand this approach based on the needs of your specific application.

Source: vultr.com

Create a Free Account

Register now and get access to our Cloud Services.

Posts you might be interested in:

No results found.