Antrian adalah alat hebat yang menskalakan hampir sempurna. Besi tidak mengatasi? Kami baru saja menambahkan node ke cluster. Ketika antrian hadir dalam sebuah proyek, itu tergoda untuk mengimplementasikan lebih banyak fungsionalitas dengan bantuannya.
Kami akan berbicara tentang perangkap jalur ini di artikel ini.
Cepat atau lambat, saat menggunakan antrian, pengguna dihadapkan pada pertanyaan untuk menggunakannya sehubungan dengan beberapa layanan, database, dll.
Pesanan selesai, Anda perlu mengirim pemberitahuan SMS ke pengguna.
Pesanan baru telah tiba, Anda perlu mengirim pemberitahuan push ke pelaksana.
Pekerjaan selesai, Anda perlu menghapus uang dari akun klien.
Dalam semua contoh di atas, perubahan dalam entitas bisnis dicatat dalam database (atau layanan dengan database), dan ada godaan besar untuk mengirim notifikasi menggunakan antrian.
Apa yang kita miliki dalam situasi ini? Struktur kode awal dan paling sederhana:
Layanan (program kami) mencatat perubahan data dalam database.
Layanan kemudian menempatkan pekerjaan dalam antrian.
Faktanya, dalam kasus ini, Anda perlu menerapkan pemicu peristiwa untuk mengubah rekaman data.
Dan dalam kasus umum, ternyata di sini kita memiliki dua record dalam dua database yang berbeda: layanan dan antrian.
Sekarang mari terjun ke dunia nyata dan pertimbangkan situasi apa yang mungkin muncul:
Semuanya baik-baik saja. DB tersedia, DB antrian tersedia;
, ;
, ;
, .
: , , .
, , ... . .
, .
, ( , , ), , :
.
.
.
.
, , .
:
, . 3 4 ( ).
. .
.
, . : , . , , .
, (, , http- /).
, .
/, ( queue
) .
, , ( ):
/* */
UPDATE
"orders"
SET
"status" = 'complete'
WHERE
"order_id" = $1
RETURNING
*
/* */
WITH "o" AS (
UPDATE
"orders"
SET
"status" = 'complete'
WHERE
"order_id" = $1
RETURNING
*
),
"q" AS (
INSERT INTO
"queue"
(
"key",
"data"
)
SELECT
"o.order_id",
"o.status"
FROM
"o"
)
SELECT
*
FROM
"o"
: queue
, , orders
.
, queue
, , . , .
:
queue
.
.
.
/
, , . , - ( , ..), :
.
, , , , O_APPEND
- .
( ) ,
.
( ) .
, , , , .
Seperti yang Anda lihat, ada beberapa opsi untuk memecahkan masalah. Jika kita ingin menjaga sistem tetap sederhana (prinsip KISS), maka pengenalan daemon tambahan dan pesan cache / log dalam database atau file / database lokal akan memberikan sedikit peningkatan dalam kompleksitas. Pada saat yang sama, sangat penting untuk menjaga handler tetap idempoten, karena jika terjadi kegagalan pada saat mentransfer tugas dari cache lokal ke antrian umum, duplikat mungkin muncul.
Solusi umum adalah menggunakan komit dua fase.