在 Ubuntu 20.04 上使用 Redis 和 PHP 设置网站点击计数器

作者選擇Apache Software Foundation作為Write for DOnations計畫的捐贈對象。

介紹

A hit counter is an application that records and indicates the number of visits your web page has received. The counter starts from 1 and is incremented once every time a web page is visited.

為了追踪訪問次數,點擊計數器應用程序需要一種形式的數據庫。儘管基於磁盤的數據庫管理系統如MySQL可以工作,但內存數據庫在速度、性能、可擴展性、簡潔性和易用性方面更好。這就是Redis服務器發揮作用的地方。Redis將數據存儲在計算機的RAM中,而不是每次執行輸入/輸出操作時都要擊中磁盤。這顯著提高了吞吐量。

為了追踪您網站的訪問,您需要一個Redis哈希映射。這是一種實現鍵值對的數據結構。哈希映射提供了一個將鍵映射到值的哈希表。一旦用戶訪問您的網頁,您就根據他們的公共IP地址或用戶名(對於已驗證的用戶)創建一個鍵,然後將他們的總訪問次數初始化為為1。然後,每次用戶重新訪問您的網頁時,您都可以根據他們的IP地址/用戶名從Redis哈希映射中檢查他們的總訪問次數並增加該值。

在本指南中,您將在Ubuntu 20.04服務器上使用Redis和PHP設置網站點擊計數器。本指南中的PHP腳本使用訪問者的公共IP地址來追踪他們的訪問。

先決條件

要跟隨本指南,請確保您擁有以下內容:

第 1 步 — 安裝 PHP Redis 擴展

在此步驟中,您將安裝一個允許 PHP 與 Redis 服務器通信的 Redis 擴展。您還將創建一個測試網頁,該網頁實現了 Redis 哈希映射以跟踪網頁訪問。

在安裝 Redis 擴展之前,刷新您的 Ubuntu 軟件包信息索引:

  1. sudo apt update

然後,執行以下命令來安裝 php-redis。此擴展提供了與 Redis 服務器鍵值存儲通信的 API:

  1. sudo apt install -y php-redis

重新啟動 Apache 以加載新的擴展:

  1. sudo systemctl restart apache2

您現在已安裝了一個 PHP 擴展,可與您的 Redis 服務器通信。接下來,您將在 Apache Web 伺服器的根目錄下創建一個 test.php 網頁。這只是一個範例文件,當訪客使用瀏覽器訪問您的網站時會請求它。在幕後,test.php 頁面文件加載一個 hit_counter.php 腳本,稍後您將創建以使用 Redis 服務器來跟蹤網頁訪問的 hit_counter.php 文件:

在現實情況下,您的網站可能有幾十甚至幾百個網頁。對於本指南,您將為演示目的設置一個單獨的網頁:

在終端窗口中,使用 nano 在您的 Web 伺服器的根目錄 /var/www/html/ 下創建一個新的 test.php 文件:

  1. sudo nano /var/www/html/test.php

然後,將以下信息輸入到 test.php 文件中:

/var/www/html/test.php
<?php
  require_once 'hit_counter.php';
?>

<!DOCTYPE html>
<html>

  <head>
    <title>Sample Test Page</title>
  </head>

  <body>
    <h1>Sample test page</h1>
    <p>This is a sample test page.</p>
  </body>

</html>

當您編輯完成後保存並關閉文件。在此步驟中,您已創建了一個簡單的 HTML 網頁,當訪問時加載一個 hit_counter.php 文件。接下來,您將編寫 hit_counter.php 文件來跟蹤測試頁面的訪問。

步驟 2 — 創建一個 Redis 點擊計數器腳本

在生產環境中工作時,將可重褐使用的 PHP 文件分開是非常常見的。這使您可以通過包含它們的路徑而不是複製粘貼代碼,在項目的不同部分實施這些文件中的邏輯。這樣做可以使維護變得更容易,因為您只需要在需要更改邏輯的情況下編輯單個文件。這樣可以節省大量時間。

您將在本指南中應用相同的策略。您將創建一個單獨的 hit_counter.php 文件,可以包含在任何需要追蹤訪問者的網頁中。

在此文件中,您將使用 php-redis 库來從 PHP 連接到 Redis 服務器。然後,您將創建一個 Redis 哈希映射,用於存儲訪問者對您的網站的訪問次數。您將使用訪問者的唯一 IP 地址作為 Redis 鍵來區分每個訪問者在 Redis 服務器中的點擊次數。

在您的終端窗口中,使用 nano 打開一個新的 hit_counter.php 文件以進行編輯:

  1. sudo nano /var/www/html/hit_counter.php

現在已經創建了 hit_counter.php 文件,打開一個新的 PHP 標籤 <?php。然後,在 try { 塊內部輸入以下代碼來連接到端口 6379 上的本地 Redis 服務器。將 EXAMPLE_PASSWORD 替換為 Redis 服務器的身份驗證密碼:

/var/www/html/hit_counter.php

<?php

    try {

        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $redis->auth('EXAMPLE_PASSWORD');

接下來,給 Redis 哈希映射($siteVisitsMap) 一個您選擇的名稱。本指南使用 siteStats 作為演示目的:

/var/www/html/hit_counter.php

        $siteVisitsMap = 'siteStats';

定義了 Redis 哈希映射後,現在要初始化一個空的 Redis 金鑰($visitorHashKey)。然後,您將用訪問者的 IP 地址填充它。您將使用 $visitorHashKey 變數的值來唯一標識每個請求您網頁的訪問者:

/var/www/html/hit_counter.php


        $visitorHashKey = '';           

        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {

            $visitorHashKey = $_SERVER['HTTP_CLIENT_IP'];

        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {

            $visitorHashKey = $_SERVER['HTTP_X_FORWARDED_FOR'];

        } else {

            $visitorHashKey = $_SERVER['REMOTE_ADDR'];
        }

在此代碼中,您使用 PHP 的 if 陳述來通過檢查是否填充了 $_SERVER['HTTP_CLIENT_IP']$_SERVER['HTTP_X_FORWARDED_FOR']$_SERVER['REMOTE_ADDR'] 變數來確定訪問者的 IP 地址。

隨後,初始化一個 $totalVisits 變數來存儲每個 IP 地址的總訪問次數,並將其賦值為 0。然後,使用 PHP 的 if (...) {...} else {...}$redis->hExists($siteVisitsMap, $visitorHashKey) 陳述來檢查 Redis 服務器中是否存在該 IP 地址的任何項目。

您將使用語句 if ($redis->hExists($siteVisitsMap, $visitorHashKey)) {...} 來檢查名為 $siteVisitsMap 的映射中是否存在一個 $visitorHashKey

如果在 Redis 服务器中存在带有命名 IP 地址的地图和密钥,则使用以下语句检索它:$visitorData = $redis->hMget($siteVisitsMap, array($visitorHashKey)); 并使用 $totalVisits = $visitorData[$visitorHashKey] + 1; 来增加 $totalVisits 变量。您正在使用 $redis->hMget 语句来获取与 IP 地址关联的点击次数数据。 hMget 函数接受您地图的名称($siteVisitsMap)和要从 Redis 服务器中检索的密钥数组。在这种情况下,您只有一个密钥($visitorHashKey),但您必须使用语句 array($visitorHashKey) 将其转换为数组。

如果您的脚本首次遇到 IP 地址,则将 $totalVisits 变量设置为 1。最后,使用 $redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits); 根据上一个 if (...) {...} else {...} 语句的结果设置 $visitorHashKey 的值。 $redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits) 语句在 Redis 服务器中创建一个名为 $visitorHashKey 的键的 $siteVisitsMap 散列映射,其值为 $totalVisits

然后,通过回显总访问次数来欢迎访客,并关闭 } catch (...) {...} 块:

/var/www/html/hit_counter.php

        $totalVisits = 0;

        if ($redis->hExists($siteVisitsMap, $visitorHashKey)) {

            $visitorData = $redis->hMget($siteVisitsMap, array($visitorHashKey));
            $totalVisits = $visitorData[$visitorHashKey] + 1;

        } else {

            $totalVisits = 1;

        }

        $redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits);

        echo "Welcome, you've visited this page " .  $totalVisits . " times\n";

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

完成后,您的 /var/www/html/hit_counter.php 文件应类似于以下代码:

/var/www/html/hit_counter.php

<?php

    try {

        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $redis->auth('EXAMPLE_PASSWORD');

        $siteVisitsMap  = 'siteStats';
        $visitorHashKey = '';           

        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {

           $visitorHashKey = $_SERVER['HTTP_CLIENT_IP'];

        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {

           $visitorHashKey = $_SERVER['HTTP_X_FORWARDED_FOR'];

        } else {

           $visitorHashKey = $_SERVER['REMOTE_ADDR'];
        }
      
        $totalVisits = 0;

        if ($redis->hExists($siteVisitsMap, $visitorHashKey)) {

            $visitorData = $redis->hMget($siteVisitsMap,  array($visitorHashKey));
            $totalVisits = $visitorData[$visitorHashKey] + 1;

        } else {

            $totalVisits = 1;

        }

        $redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits);

        echo "Welcome, you've visited this page " .  $totalVisits . " times\n";

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

完成編輯後,儲存並關閉檔案。現在,您已經編寫了一個 hit_counter.php 腳本。接下來,您將創建另一個 PHP 腳本,從 Redis 哈希映射中收集的數據生成報告。

第 3 步 — 創建站點統計報告腳本

一旦您在 Redis 哈希映射中收集了數據,如果無法檢索並以報告形式呈現信息,則這些數據可能毫無意義。在此步驟中,您將創建一個日誌報告,顯示不同的網站訪問者以及他們在測試網頁上總共的訪問次數。

要創建日誌報告腳本,請在終端窗口上運行 nano 並創建一個新的 /var/www/html/log_report.php 檔案:

  1. sudo nano /var/www/html/log_report.php

然後,將以下信息輸入到檔案中。將 EXAMPLE_PASSWORD 替換為 Redis 伺服器的正確密碼:

/var/www/html/log.php

<!DOCTYPE html>
<html>

  <head>
    <title>Site Visits Report</title>
  </head>

  <body>

      <h1>Site Visits Report</h1>

      <table border = '1'>
        <tr>
          <th>No.</th>
          <th>Visitor</th>
          <th>Total Visits</th>
        </tr>

        <?php

            try {

                $redis = new Redis();
                $redis->connect('127.0.0.1', 6379);
                $redis->auth('EXAMPLE_PASSWORD');

                $siteVisitsMap = 'siteStats';                          

                $siteStats = $redis->HGETALL($siteVisitsMap);

                $i = 1; 

                foreach ($siteStats as $visitor => $totalVisits) {

                    echo "<tr>";
                      echo "<td align = 'left'>"   . $i . "."     . "</td>";
                      echo "<td align = 'left'>"   . $visitor     . "</td>";
                      echo "<td align = 'right'>"  . $totalVisits . "</td>";
                    echo "</tr>";
                    
                    $i++;
                }

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

        ?>

      </table>
  </body>

</html>

當您完成編輯時,請保存並關閉文件。在上述腳本中,您正在連接到 Redis 伺服器,並使用語句 $redis->HGETALL($siteVisitsMap); 檢索網頁訪問的哈希映射。然後,您使用 PHP foreach ($siteStats as $visitor => $totalVisits) { 語句循環並顯示訪問者的 IP 地址以及他們對您的站點所做的訪問次數。您使用 Redis HGETALL 命令從 siteVisitsMap 映射檢索所有字段(IP 地址)和值(每個 IP 地址的總訪問次數)。

您現在有一個測試頁面、一個點擊計數器腳本和一個報告頁面來檢查您的站點統計信息。接下來,您將測試您的點擊計數器的功能,並查看一切是否正常運作。

步驟 4 — 測試 Redis 點擊計數器

在這一步中,您將測試點擊計數器的整個邏輯。在您的 Web 瀏覽器中導航到以下 URL。將 your-server-IP 替換為您服務器的公共 IP 地址或域名。

http://your-server-IP/test.php

使用不同的設備刷新頁面幾次以生成足夠的統計信息。每次訪問後,您應該收到以下輸出。

接下來,訪問以下 URL 以在 HTML 表格中顯示您的站點訪問報告

http://your-server-IP/log_report.php

您現在應該會看到類似以下輸出的報告。

您的點擊計數器現在按預期運行。

結論

在本指南中,您已經在Ubuntu 20.04伺服器上使用Redis和PHP設置了網站點擊計數器。

從本指南中的示例源代碼可以看出,Redis提供了更清晰的方法來創建和更新哈希映射。

正如本指南開頭所提到的,使用關聯式數據庫管理系統可能仍然有效,但您將需要撰寫大量代碼來插入和更新底層表中的數據。此外,基於磁盤的數據庫在您的網站增長時可能會遇到擴展性問題。

有關在內存中使用Redis的更多信息,請參閱以下指南:

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-website-hit-counter-with-redis-and-php-on-ubuntu-20-04