Mengapa Pemesejan Tak Segerak
Lihat cara baris gilir mengasingkan pengeluar daripada pengguna.
Mengapa Pemesejan Tak Segerak ialah pelajaran PHP Academy percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran PHP Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus PHP Academy merangkumi sejumlah 4 pelajaran.
Mengapa Pemesejan Tak Segerak
Dalam permintaan segerak, proses PHP anda tersekat apabila berkomunikasi dengan get laluan e-mel, pemproses pembayaran atau perkhidmatan hiliran. Di bawah beban, keadaan ini mengikat kependaman dan ketersediaan anda kepada setiap kebergantungan yang dipanggil. Pemesejan tak segerak memutuskan rantaian itu: pengeluar meletakkan mesej ke dalam baris gilir lalu kembali serta-merta; pengguna mesej memprosesnya kemudian mengikut kadar mereka sendiri.
Pelajaran ini menerangkan sebabnya — penyahgandingan, penimbalan dan pertukaran antara jaminan penghantaran yang perlu anda fahami sebelum menggunakan RabbitMQ atau Kafka.
Penyahgandingan Mengikut Masa dan Ruang
Baris gilir menyahgandingkan pengeluar dan pengguna mesej pada dua paksi:
- Ruang — kedua-dua pihak tidak memerlukan alamat pihak yang satu lagi; mereka hanya mengetahui perantara.
- Masa — pengguna mesej boleh tidak tersedia ketika pengeluar menerbitkan mesej; mesej itu menunggu.
Versi segerak di bawah mengikat permintaan web pada ketersediaan dan kelajuan pelayan mel.
<?php
// Synchronous: the HTTP request blocks on SMTP
function registerUser(string $email): void {
saveUser($email);
// If SMTP is slow or down, the user waits or the request fails
sendWelcomeEmail($email); // 800ms blocking call
echo "Registered\n";
}
function saveUser(string $e): void { /* ... */ }
function sendWelcomeEmail(string $e): void { usleep(1); }
registerUser('dev@example.com');Terbitkan dan Teruskan
Versi tak segerak menyimpan pengguna, menerbitkan mesej UserRegistered dan kembali. Pekerja berasingan menghantar e-mel tersebut. Kependaman HTTP kini hanya bergantung pada penerbitan pantas kepada perantara setempat, bukannya perjalanan pergi balik SMTP.
<?php
function registerUser(string $email): void {
saveUser($email);
// Publish a lightweight event; worker handles email later
publish('user.registered', json_encode(['email' => $email]));
echo "Registered (email queued)\n";
}
function saveUser(string $e): void { /* ... */ }
function publish(string $routingKey, string $payload): void {
echo "-> queued $routingKey: $payload\n";
}
registerUser('dev@example.com');Perataan Beban (Penimbalan)
Lonjakan trafik tidak sekata, manakala kapasiti pemprosesan adalah tetap. Baris gilir bertindak sebagai penimbal: ia menyerap lonjakan 10,000 mesej dan membolehkan kumpulan pekerja mengosongkannya pada kadar yang mampan. Tanpa baris gilir, lonjakan itu akan membebankan pangkalan data atau API hiliran secara langsung.
Inilah perataan beban — anda menukar kependaman (mesej mungkin menunggu sebentar) dengan kestabilan (tiada apa-apa yang gagal).
Jaminan Penghantaran
Setiap sistem pemesejan membuat satu janji penghantaran. Ketahui jaminan yang anda gunakan:
- Paling sekali — hantar dan lupakan; mesej mungkin hilang tetapi tidak pernah diduplikasi.
- Sekurang-kurangnya sekali — dihantar semula sehingga disahkan; pendua mungkin berlaku. Ini ialah lalai yang biasa.
- Tepat sekali — tiada kehilangan dan tiada pendua; mahal serta sering hanya merupakan ilusi separa pada lapisan aplikasi.
Oleh sebab kebanyakan sistem sebenar memberikan sekurang-kurangnya sekali, pengguna mesej anda mesti mampu menangani mesej yang sama dua kali.
Pengguna Idempoten
Penyelesaian untuk pendua sekurang-kurangnya sekali ialah idempotensi: memproses mesej dua kali menghasilkan keputusan yang sama seperti memprosesnya sekali. Teknik biasa ialah menggunakan kunci penyahpenduaan (ID mesej) yang disimpan dalam indeks unik.
<?php
function handle(array $msg, PDO $pdo): void {
$pdo->beginTransaction();
try {
// Unique constraint on message_id makes the insert the dedup gate
$stmt = $pdo->prepare(
'INSERT INTO processed_messages (id) VALUES (?)'
);
$stmt->execute([$msg['id']]);
} catch (PDOException $e) {
$pdo->rollBack();
echo "Duplicate {$msg['id']} skipped\n";
return; // already handled
}
chargeCustomer($msg['amount']);
$pdo->commit();
}
function chargeCustomer(int $a): void {}Pengesahan dan Penghantaran Semula
Pengguna mesej menandakan kejayaan dengan pengesahan. Jika prosesnya terhenti sebelum menghantar pengesahan, perantara menghantar semula mesej itu kepada pengguna mesej yang lain. Inilah yang membolehkan penghantaran sekurang-kurangnya sekali berfungsi — tetapi ini bermakna ack mesti datang selepas kesan sampingan dimuktamadkan, bukan sebelumnya.
Buat pengesahan terlalu awal dan proses yang terhenti akan menyebabkan mesej hilang. Buat pengesahan terlalu lewat lalu proses terhenti, dan anda mendapat pendua — yang akan ditangani oleh lapisan idempotensi anda.
<?php
// Pseudocode of the consumer contract
function consumeLoop($channel): void {
while ($msg = $channel->get()) {
try {
processSideEffect($msg); // commit DB write first
$channel->ack($msg); // only then ack
} catch (\Throwable $e) {
$channel->nack($msg, requeue: true); // let it redeliver
}
}
}
function processSideEffect($m): void {}Urutan Bukan Percuma
Baris gilir tidak menjamin urutan global apabila pengguna mesej ditambah. Dua pekerja yang mengambil mesej daripada baris gilir yang sama memprosesnya secara serentak, jadi mesej B mungkin selesai sebelum mesej A.
Jika urutan penting (contohnya delta baki akaun), anda mesti membahagikan mengikut kunci supaya semua mesej berkaitan pergi kepada seorang pengguna mesej yang sama mengikut urutan. Kafka melakukan perkara ini secara asli dengan pembahagian; dengan RabbitMQ, anda menghalakan mesej menggunakan cincangan konsisten kepada baris gilir mengikut kunci.
Baris Gilir Surat Mati
Sesetengah mesej tidak mungkin berjaya — muatan yang cacat atau rujukan kepada baris yang telah dipadam. Percubaan semula tanpa henti menyekat baris gilir (mesej beracun). Coraknya ialah baris gilir surat mati (DLQ): selepas N percubaan gagal, alihkan mesej itu ke tempat lain untuk diperiksa dan bukannya menghantarnya semula.
<?php
function consume(array $msg, $channel): void {
$attempts = ($msg['headers']['x-attempt'] ?? 0) + 1;
try {
process($msg);
$channel->ack($msg);
} catch (\Throwable $e) {
if ($attempts >= 5) {
$channel->deadLetter($msg); // park in DLQ
} else {
$channel->republish($msg, ['x-attempt' => $attempts]);
}
}
}
function process(array $m): void {}Bila NOT Patut Menggunakan Baris Gilir
Pemesejan tak segerak menambah kos operasi sebenar: perantara yang perlu dikendalikan, ketekalan akhirnya yang perlu diterangkan kepada pasukan produk dan penyahpepijatan yang lebih sukar merentas sempadan proses.
Gunakan baris gilir apabila kerja itu lambat, berlonjakan, boleh dicuba semula atau hantar-dan-lupakan. Kekalkan kaedah segerak apabila pemanggil benar-benar memerlukan hasilnya sekarang (contohnya harga sahih yang mesti dilihat oleh pengguna) — membalut panggilan yang memerlukan jawapan dalam baris gilir hanya menambah kependaman dan kerumitan.
Baris Gilir berbanding Catatan
Dua bentuk umum perantara menyokong corak ini, dan kedua-duanya akan digunakan dalam baki kursus ini:
- Baris gilir tugas (RabbitMQ) memadam mesej selepas mesej itu disahkan. Ia cemerlang dalam mengagihkan kerja kepada kumpulan pengguna mesej yang bersaing, dengan penghalaan setiap mesej dan tempoh hayat.
- Catatan komit (Kafka) menyimpan mesej mengikut tempoh pengekalan; setiap pengguna mesej menjejaki ofsetnya sendiri dan boleh memainkan semula sejarah, manakala banyak kumpulan pengguna mesej bebas membaca strim yang sama.
Pilih baris gilir untuk pengagihan kerja, dan catatan untuk strim peristiwa berdaya pemprosesan tinggi serta main semula.
<?php
$useCase = 'replay events for a new analytics service';
$broker = str_contains($useCase, 'replay') || str_contains($useCase, 'stream')
? 'Kafka (commit log)'
: 'RabbitMQ (task queue)';
echo $broker . "\n";Semakan Pantas
Penaakulan tentang jaminan penghantaran.
Ringkasan
Kini anda mempunyai gambaran mental di sebalik pemesejan tak segerak:
- Baris gilir memberikan penyahgandingan ruang + masa dan bertindak sebagai penimbal untuk perataan beban.
- Kebanyakan sistem menggunakan sekurang-kurangnya sekali, jadi pengguna mesej mesti idempoten.
- Buat pengesahan selepas kesan sampingan dimuktamadkan; biarkan kegagalan menyebabkan penghantaran semula.
- Urutan memerlukan pembahagian mengikut kunci; mesej beracun memerlukan DLQ.
- Jangan masukkan ke baris gilir kerja yang perlu dijawab oleh pemanggil secara segerak.
Seterusnya, anda akan mempraktikkan perkara ini dengan RabbitMQ dalam PHP.
Pelajari PHP dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 49
- Pelajaran
- 195
Soalan Lazim
Adakah pelajaran “Mengapa Pemesejan Tak Segerak” percuma?
Ya — teks penuh “Mengapa Pemesejan Tak Segerak” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus PHP Academy, tingkat taraf kepada CoddyKit PRO. Kursus PHP Academy merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Mengapa Pemesejan Tak Segerak”?
Lihat cara baris gilir mengasingkan pengeluar daripada pengguna. Anda berlatih PHP Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan PHP Academy?
Tiada pengalaman terdahulu diperlukan. Pembelajaran PHP Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.
Berapa lamakah pelajaran “Mengapa Pemesejan Tak Segerak” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran PHP Academy ini?
Ya. Setiap pelajaran PHP Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Mengapa Pemesejan Tak Segerak
- Bekerja dengan RabbitMQ dalam PHP
- Apache Kafka dengan PHP
- Membina Aliran Kerja Dipacu Peristiwa