Introduction
A Redis hash map is a data type that stores key-pair values as an associative array. By using Redis hash tables, you can benefit from fast lookups and flexible keys. These advantages make Redis the perfect NoSQL database for creating a hit counter for your applications or websites. The hit counter stores the number of visits made to a web resource in your server. Because Redis is an in-memory database, it is several times faster than even the fastest SSD in the market today and is suitable for this job.
You'll set up a web counter on Ubuntu 20.04 using a Redis hash map in this guide. When a PHP web resource on your server receives a visit, Redis will increment a counter based on each visitor's IP address. You'll also create a human-readable report to display hit counts for each user making visits to the resource on your server.
Prerequisites
This guide requires:
- An Ubuntu 20.04 server.
- A sudo user.
- A LAMP Stack.
- A Redis Server. You may skip the installing MySQL server, which is not required for this guide.
Install php-redis
Extension
To begin, SSH to your server and install the php-redis
library. This is an extension that allows you to use the Redis functionalities within the PHP code.
$ sudo apt update
$ sudo apt install -y php-redis
Restart Apache to load the php-redis
module.
$ sudo systemctl restart apache2
Create a Sample Web Resource File
With the php-redis
library in place, you'll create a sample_resource.php
file. In this file, you'll determine the visitor's IP address and log the number of visits they've made to the server.
Open the file /var/www/html/sample_resource.php
using nano.
$ sudo nano /var/www/html/sample_resource.php
Add the information below into the file.
<?php
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$client_ip_address = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$client_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$client_ip_address = $_SERVER['REMOTE_ADDR'];
}
if ($redis->hExists('visitor_stats', $client_ip_address)) {
$my_array = $redis->hMget("visitor_stats", array($client_ip_address));
$total_counts = $my_array[$client_ip_address] + 1;
} else {
$total_counts = 1;
}
$redis->hSet('visitor_stats', $client_ip_address, $total_counts);
echo "Welcome, your IP is " . $client_ip_address . ". You've visited this page ". $total_counts . " times\n";
} catch (Exception $e) {
echo $e->getMessage();
}
?>
Once you're through with editing, save the file by pressing Ctrl + X, then Y and Enter.
The sample_resource.php
explained:
The below code connects to your local Redis server on port
6379
.$redis = new Redis(); $redis->connect('127.0.0.1', 6379);
You've used the code snippet below to retrieve the client's IP address.
if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $client_ip_address = $_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $client_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $client_ip_address = $_SERVER['REMOTE_ADDR']; }
In the below code, you're using the Redis
hMget
method to check if the hash tablevisitor_stats
contains a key identified by the client IP address variable ($client_ip_address
). If the key exists, you're retrieving the total count of visits using the statement$total_counts = $my_array[$client_ip_address] + 1;
. Otherwise, in case this is the first time a client is making a visit, you're initializing the counts to1
using the PHP code$total_counts = 1;
if ($redis->hExists('visitor_stats', $client_ip_address)) { $my_array = $redis->hMget("visitor_stats", array($client_ip_address)); $total_counts = $my_array[$client_ip_address] + 1; } else { $total_counts = 1; }
Finally, you're setting a new value for the client visiting the web resource using the Redis
hSet
function. You've also used the PHPecho
command to display the number of visits a client has made to the web resource.$redis->hSet('visitor_stats', $client_ip_address, $total_counts); echo "Welcome, your IP is " . $client_ip_address . ". You've visited this page ". $total_counts . " times\n";
Once you've coded and closed the /var/www/html/sample_resource.php
, you'll test it in the next step to see if it is working as expected.
Testing the Resource File
Use Linux curl
command to request the sample_resource.php
resource file that you've created.
$ curl localhost/sample_resource.php
You should see the output below showing the number of times you've visited the resource because this is the first time. The total counts should be 1
.
Welcome, your IP is 127.0.0.1. You've visited this page 1 times
Display Human Readable Stats
Create a detailed report file that shows the total visits made and group them by the IP addresses. Open /var/www/html/stats.php
using nano.
$ sudo nano /var/www/html/stats.php
Then, add the information below into the file.
<?php
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$stats = $redis->HGETALL("visitor_stats");
echo "\nIP ADDRESS VISITS\n";
echo "--------- ------\n";
foreach ($stats as $key => $value) {
echo $key . "\t" . $value . "\n";
}
} catch (Exception $e) {
echo $e->getMessage();
}
?>
In the above file, you are using the Redis HGETALL
function to create an array of IP addresses and their total visits registered to the Redis server. Then, you're using the PHP ...foreach(...){...}...
statement to loop through the list and echo
out each visitor's total visits in a new line.
After you've finished editing the file, save and close it. Next, run a curl
command against the resource to get the report.
$ curl localhost/stats.php
You should see an output like the one shown below. Please note, this output may be different depending on the number of visits that you've made to the localhost/sample_resource.php
page.
IP ADDRESS VISITS
--------- ------
127.0.0.1 1
IP ADDRESS 2 1
IP ADDRESS 3 1
The output above confirms that the Redis hit counter is working as expected.
Conclusion
In this guide, you've used the Redis hash map to create a hit counter with PHP on Ubuntu 20.04. You may extend the code in this tutorial to suit your needs when implementing a web counter depending on your use-case.