Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mekanisme pengesahan mesej baris gilir dan kaedah pemprosesan cuba semula mesej dalam PHP dan MySQL

Mekanisme pengesahan mesej baris gilir dan kaedah pemprosesan cuba semula mesej dalam PHP dan MySQL

WBOY
WBOYasal
2023-10-15 12:31:431195semak imbas

Mekanisme pengesahan mesej baris gilir dan kaedah pemprosesan cuba semula mesej dalam PHP dan MySQL

Mekanisme pengesahan mesej giliran dan kaedah pemprosesan semula mesej dalam PHP dan MySQL

Pengenalan:
Dengan pembangunan aplikasi Internet, banyak perkhidmatan dalam talian perlu mengendalikan sejumlah besar permintaan, dan permintaan ini selalunya memerlukan kaedah pemprosesan tak segerak . Baris gilir ialah penyelesaian biasa yang boleh memisahkan permintaan daripada pemprosesan, meningkatkan prestasi sistem dan kebolehpercayaan secara berkesan. Artikel ini akan memperkenalkan mekanisme pengesahan mesej dan kaedah pemprosesan cuba semula mesej baris gilir dalam PHP dan MySQL, dan memberikan contoh kod khusus.

1. Konsep dan fungsi baris gilir mesej
Baris gilir mesej ialah mod aplikasi biasa, yang menyimpan mesej dalam baris gilir dan kemudian memprosesnya secara tidak segerak. Faedah baris gilir mesej dicerminkan terutamanya dalam aspek berikut:

  1. Penyahgandingan: menyah gandingan permintaan dan pemprosesan untuk meningkatkan kebolehskalaan dan kebolehselenggaraan sistem.
  2. Pemprosesan tak segerak: Letakkan operasi yang memakan masa dalam baris gilir untuk pemprosesan tak segerak bagi meningkatkan kelajuan tindak balas sistem.
  3. Mekanisme toleransi kesalahan untuk pemprosesan yang gagal: Kebolehpercayaan pemprosesan mesej dipastikan melalui pengesahan mesej dan mekanisme cuba semula mesej.

2. Mekanisme Pengesahan Mesej
Dalam sistem giliran, pengesahan mesej adalah mekanisme untuk memastikan selesainya pemprosesan mesej. Mekanisme penerimaan mesej membantu mengelakkan masalah kehilangan mesej atau pemprosesan pendua.

Pengakuan mesej dalam PHP boleh dicapai dengan menggunakan mekanisme ACK. Langkah pelaksanaan khusus adalah seperti berikut:

  1. Pengeluar menghantar mesej ke baris gilir.
  2. Pengguna mengambil mesej dari baris gilir untuk diproses.
  3. Jika pemprosesan mesej berjaya, pengguna menghantar ACK untuk mengesahkan bahawa pemprosesan mesej telah selesai jika tidak, pengguna menghantar NACK untuk menolak pemprosesan mesej.
  4. Baris gilir mengakui penerimaan ACK atau NACK mesej dan mengalih keluar mesej ACK daripada baris gilir.

Berikut ialah contoh kod menggunakan RabbitMQ sebagai baris gilir mesej:
Pengeluar:

#!/usr/bin/env php
<?php
require_once __DIR__ . '/../vendor/autoload.php';

use PhpAmqpLibConnectionAMQPStreamConnection;
use PhpAmqpLibMessageAMQPMessage;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('queue_name', false, false, false, false);

$msg = new AMQPMessage('Hello World!');
$channel->basic_publish($msg, '', 'queue_name');

$channel->close();
$connection->close();

Pengguna:

#!/usr/bin/env php
<?php
require_once __DIR__ . '/../vendor/autoload.php';

use PhpAmqpLibConnectionAMQPStreamConnection;
use PhpAmqpLibMessageAMQPMessage;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('queue_name', false, false, false, false);

$callback = function (AMQPMessage $msg) {
    echo 'Received message: ' . $msg->body . PHP_EOL;
    if (processMessage($msg)) {
        $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']); // 消息处理成功,发送ACK确认
    } else {
        $msg->delivery_info['channel']->basic_nack($msg->delivery_info['delivery_tag'], false, true); // 消息处理失败,发送NACK拒绝
    }
};

$channel->basic_consume('queue_name', '', false, false, false, false, $callback);
while (count($channel->callbacks)) {
    $channel->wait();
}

function processMessage(AMQPMessage $msg) {
    // 消息处理逻辑
    if ($msg->body == 'Hello World!') {
        return true;
    } else {
        return false;
    }
}

$channel->close();
$connection->close();

3 Kaedah pemprosesan cuba semula mesej
Dalam aplikasi sebenar, pemprosesan mesej mungkin gagal, contohnya kegagalan rangkaian, pelayan , dsb. Untuk memastikan kebolehpercayaan mesej, mesej yang gagal diproses boleh dicuba semula.

MySQL menyediakan mekanisme transaksi dan rollback, yang boleh digunakan dalam pemprosesan cuba semula mesej. Langkah pelaksanaan khusus adalah seperti berikut:

  1. Pengeluar menghantar mesej ke jadual mesej dalam pangkalan data.
  2. Pengguna mengeluarkan mesej daripada jadual mesej dalam pangkalan data untuk diproses.
  3. Jika mesej berjaya diproses, padamkan mesej daripada jadual mesej jika tidak, tambah satu pada bilangan masa pemprosesan dalam jadual mesej dan kemas kini masa pemprosesan.
  4. Sediakan tugas berjadual untuk menyemak mesej dalam jadual mesej yang telah diproses kurang daripada atau sama dengan bilangan maksimum percubaan semula secara kerap dan hantar semula kepada pengguna.

Berikut ialah contoh kod menggunakan MySQL sebagai storan mesej:
Pengeluar:

<?php
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'root';
$password = '';

try {
    $db = new PDO($dsn, $user, $password);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = 'INSERT INTO message_queue (message) VALUES (?)';
    $stmt = $db->prepare($sql);
    $message = 'Hello World!';
    $stmt->bindParam(1, $message);
    $stmt->execute();

} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

Pengguna:

<?php
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'root';
$password = '';

try {
    $db = new PDO($dsn, $user, $password);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = 'SELECT * FROM message_queue';
    $stmt = $db->prepare($sql);
    $stmt->execute();
    $messages = $stmt->fetchAll();

    foreach ($messages as $message) {
        if (processMessage($message)) {
            $deleteSql = 'DELETE FROM message_queue WHERE id = ?';
            $deleteStmt = $db->prepare($deleteSql);
            $deleteStmt->bindParam(1, $message['id']);
            $deleteStmt->execute();
        } else {
            $retrySql = 'UPDATE message_queue SET retries = retries + 1, last_retry_time = ? WHERE id = ?';
            $retryStmt = $db->prepare($retrySql);
            $now = date('Y-m-d H:i:s');
            $retryStmt->bindParam(1, $now);
            $retryStmt->bindParam(2, $message['id']);
            $retryStmt->execute();
        }
    }

} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

function processMessage($message) {
    // 消息处理逻辑
    if ($message['message'] == 'Hello World!') {
        return true;
    } else {
        return false;
    }
}

Jadualkan tugas:

<?php
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'root';
$password = '';

try {
    $db = new PDO($dsn, $user, $password);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = 'SELECT * FROM message_queue WHERE retries <= ?';
    $stmt = $db->prepare($sql);
    $maxRetries = 3;
    $stmt->bindParam(1, $maxRetries);
    $stmt->execute();
    $messages = $stmt->fetchAll();

    foreach ($messages as $message) {
        // 重新投递消息给消费者
    }

} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

Kesimpulan:
Melalui proses pengesahan semula mesej, kita boleh mencuba semula kaedah dan mesej. kebolehpercayaan dan kestabilan sistem. Sebagai alat penyahgandingan dan pemprosesan tak segerak yang biasa, baris gilir boleh melaksanakan pengesahan mesej dengan berkesan dan mencuba semula dalam PHP dan MySQL, memberikan prestasi dan pengalaman pengguna yang lebih baik untuk aplikasi kami.

Rujukan:

  1. Dokumentasi rasmi PHP RabbitMQ: https://github.com/php-amqplib/php-amqplib
  2. Dokumentasi rasmi PHP MySQL: https://www.php.net/manual/en/book . pdo.php

Atas ialah kandungan terperinci Mekanisme pengesahan mesej baris gilir dan kaedah pemprosesan cuba semula mesej dalam PHP dan MySQL. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn