Memilih Teknologi Antrean Postgres
(adriano.fyi)- Sebelum mengadopsi sistem antrean terpisah, jika antrean pekerjaan latar belakang bisa dibangun hanya dengan Postgres yang sudah digunakan, kesederhanaan operasional dan keakraban tim bisa dimanfaatkan secara besar
NOTIFY/LISTENdanFOR UPDATE SKIP LOCKEDsejak Postgres 9.5 bersama-sama menyelesaikan notifikasi pekerjaan baru dan pencegahan pemrosesan ganda antar-pekerja- Redis, Kafka, RabbitMQ, dan Amazon SQS adalah opsi yang kuat, tetapi dependensi baru menambahkan mode kegagalan dan biaya pembelajaran ke lingkungan pengembangan, pengujian, dan operasional
- Antrean Postgres juga bukan solusi serba bisa: push/pop bisa lebih lambat daripada Redis, dan bisa muncul biaya operasional seperti database atau server antrean terpisah, serta
VACUUMyang lebih sering - Lebih aman jika kode pekerjaan latar belakang diabstraksikan agar tidak terikat pada backend antrean, dan teknologi antrean lain baru dipertimbangkan saat teknologi yang sudah akrab tidak lagi memenuhi kebutuhan
Cara kerja antrean Postgres
- Teknologi antrean Postgres terdiri dari dua elemen
- pub/sub untuk memberi tahu dan menerima pekerjaan baru
- penguncian baris untuk mencegah beberapa pekerja memproses pekerjaan yang sama
- Kedua fitur ini tersedia secara bawaan sejak Postgres 9.5 yang dirilis pada 2016
- Dengan menggunakan
NOTIFYdanLISTENbersama, pub/sub dapat ditambahkan ke aplikasi FOR UPDATE SKIP LOCKEDmengambil kunci baris pada record yang sesuai kondisi, lalu melewati record yang sudah terkunci- Jika diterapkan pada record pekerjaan, kita bisa membuat kueri pemrosesan antrean seperti
SELECT * FROM jobs ORDER BY created_at FOR UPDATE SKIP LOCKED LIMIT 1
- Jika diterapkan pada record pekerjaan, kita bisa membuat kueri pemrosesan antrean seperti
SKIP LOCKEDmemberikan tampilan data yang “tidak konsisten”, tetapi sifat ini justru berguna untuk antrean- Pekerjaan yang sedang diproses tidak terlihat oleh pekerja lain karena kunci baris
- Perilaku ini memungkinkan mutual exclusion terdistribusi
- Dengan memberi tahu pekerja yang sedang
LISTENlewatNOTIFYtentang pekerjaan baru, kita bisa membangun pemrosesan batch berkala maupun pemrosesan pekerjaan real-time
Mengapa Redis menjadi pilihan default untuk pekerjaan latar belakang
- Cara menangani pekerjaan yang berjalan lama adalah pilihan teknologi yang melibatkan banyak trade-off
- Opsi antrean/message broker yang umum digunakan antara lain
- Redis: penyimpanan data in-memory dan backend bagi berbagai library pekerjaan latar belakang
- Apache Kafka: platform distributed event streaming yang dikelola Apache Foundation
- RabbitMQ: diperkenalkan sebagai message broker yang tersebar luas
- Amazon SQS: SaaS Amazon yang menyediakan antrean dengan skalabilitas tinggi
- Di topik background jobs GitHub, 5 library terpopuler semuanya berbasis Redis
- Redis menyimpan data di memori sehingga penyisipan dan pengambilan cepat, serta menyediakan API pub/sub dan struktur data
list,setyang cocok untuk implementasi antrean - Skalabilitas Redis menjadikannya pilihan default bagi banyak pengembang, dan default punya pengaruh besar dalam pemilihan teknologi
Kriteria yang perlu dilihat sebelum skalabilitas
- Obsesi industri teknologi terhadap “scale” dapat mengesampingkan kesederhanaan, kemudahan pemeliharaan, dan pengurangan beban kognitif pengembang
- Banyak aplikasi tidak membutuhkan skala setingkat Google, Facebook, atau Uber
- Saat memulai proyek atau bisnis, alih-alih langsung mengoptimalkan hanya untuk skalabilitas, perlu lebih dulu melihat kriteria berikut
- teknologi yang sangat dipahami tim
- teknologi yang cukup baik untuk memenuhi kebutuhan pengguna
- solusi yang sesuai kapasitas tim dan membutuhkan usaha paling sedikit
- Postgres juga sebenarnya dapat diskalakan dengan baik, tetapi untuk use case antrean, ia bukan sistem antrean khusus yang paling besar skalanya
- Sebagai perangkat lunak serbaguna, Postgres menangani cukup banyak pekerjaan dengan baik, dan antrean adalah salah satunya
Menilai dengan “teknologi yang membosankan”
- Saat memilih teknologi antrean, pertanyaan terpenting adalah teknologi apa yang sedang digunakan saat ini dan benar-benar dipahami dengan baik
- Teknologi yang sudah dipakai dan dipahami dengan baik menambah beban yang lebih kecil pada software stack
- Jika sudah memakai database relasional dan database itu adalah Postgres, maka antrean Postgres bisa dipertimbangkan sebelum perangkat lunak lain
- “Teknologi yang membosankan” bukan daftar tetap, melainkan berubah tergantung teknologi yang sedang digunakan
- Untuk aplikasi yang berpusat pada pengiriman pesan, RabbitMQ bisa menjadi teknologi yang membosankan
- Untuk aplikasi yang berpusat pada caching, Redis bisa menjadi teknologi yang membosankan
- Untuk aplikasi dengan banyak data relasional, Postgres bisa menjadi teknologi yang membosankan
- Jika Redis, Kafka, RabbitMQ, atau SQS diperkenalkan baru hanya untuk pekerjaan latar belakang, biayanya menjadi besar
- dependensi sistem baru ditambahkan ke lingkungan pengembangan, pengujian, dan produksi
- di masa depan Developer, DBA, dan SRE harus memahami mode kegagalan dan pengaturan sistem baru itu
- diperlukan pengetahuan untuk pemulihan gangguan, diagnosis masalah, dan pemantauan kinerja
- unknown unknowns yang belum diketahui tim tetap menjadi risiko
Biaya dan kriteria memilih antrean Postgres
- Teknologi yang membosankan bukan solusi serba bisa, dan Postgres bukan pengecualian
- Dengan memilih antrean Postgres, kita mendapat keuntungan berupa keakraban, mode kegagalan yang sudah dikenal, dan penyebaran biaya, tetapi juga harus membayar harga berikut
- push/pop antrean Postgres jauh lebih lambat daripada Redis
- alih-alih satu database relasional, mungkin dibutuhkan database aplikasi dan database antrean yang terpisah
- untuk menskalakan pekerjaan latar belakang secara independen, mungkin dibutuhkan server database terpisah
VACUUMyang lebih sering mungkin diperlukan dan dapat menambah beban kinerja
- Tidak satu pun dari Postgres, Redis, Kafka, RabbitMQ, atau SQS yang seharusnya menjadi default otomatis
- Pemilihan teknologi selalu merupakan trade-off yang berkelanjutan, dan harus dinilai sesuai kebutuhan tim dan aplikasi
- Saat ragu, kita bisa menerapkan patokan: “pertimbangkan alternatif hanya ketika sudah terbukti bahwa teknologi yang membosankan tidak memenuhi kebutuhan”
Struktur pekerjaan latar belakang yang memungkinkan antrean diganti
- Kode pemrosesan pekerjaan latar belakang tidak boleh bergantung pada teknologi antrean tertentu
- Saat aplikasi tumbuh, teknologi seperti memcached atau Redis bisa ditambahkan sesuai kebutuhan, dan seiring waktu teknologi itu juga bisa menjadi “teknologi yang membosankan” yang akrab bagi tim
- Jika teknologi antrean diabstraksikan, pengguna dapat memilih antrean yang sesuai untuk pekerjaannya
- Di antara library pekerjaan latar belakang paling populer di GitHub, selain Hangfire, tidak ada yang menyediakan jalan keluar ke teknologi antrean selain Redis
- Dalam struktur seperti ini, untuk mengganti antrean, kode aplikasi harus ditulis ulang
- Neoq adalah library Go yang dibuat berdasarkan filosofi ini
- backend antreannya dapat menggunakan in-memory, Postgres, atau Redis
- pengguna dapat menginisialisasi dengan backend antrean lain tanpa mengubah kode aplikasi
- implementasi in-memory dan Postgres disediakan sebagai implementasi utama, sedangkan implementasi Redis menggunakan asynq
- Redis, Kafka, RabbitMQ, dan SQS bisa menjadi teknologi yang hebat, tetapi tidak selalu merupakan antrean yang tepat atau tingkat kompleksitas yang sesuai untuk pekerjaan tersebut
1 komentar
Pendapat Hacker News
Sejauh ini saya sudah membuat sistem kerja terdistribusi tiga kali, dan aturan praktis yang saya sarankan selama bertahun-tahun adalah “rancang untuk 10 kali skala saat ini”
Jika sekarang 70 request per detik, jadikan 700 request sebagai patokan; jika butuh 20 server batch job, jadikan 200 server sebagai patokan. Bahkan startup yang tumbuh 100% setiap tahun pun baru menjadi 8 kali lebih besar setelah 3 tahun, jadi masih ada waktu untuk menulis ulang sambil bertumbuh
Sistem pertama yang saya buat menghindari SQL karena alasan “skalabilitas”, tetapi saya kesulitan karena banyak menemui kasus pengecualian yang membutuhkan integritas transaksi
Dua sistem kerja terdistribusi yang saya buat setelahnya menggunakan PostgreSQL sebagai koordinator, dan secara harfiah dibangun di sekitar
SELECT FOR UPDATE SKIP LOCKED. Yang satu biasanya mengendalikan 350 worker, dan yang lain menerapkan prioritas kompleks pada ribuan pekerjaanKeduanya akan bertahan tanpa masalah sampai mencapai skala pendapatan tahunan jutaan dolar, dan misalnya sistem dengan 350 worker itu, dengan sedikit penyesuaian, bisa diskalakan hingga sekitar 2.000 CPU
Teknologi skala sangat besar tampak cukup murah sampai Anda menyadari bahwa Anda membutuhkan transaksi. Namun sejak saat itu, meniru semantik transaksi di atas penyimpanan yang bersifat eventual consistency menjadi mimpi buruk engineering
Jadi Anda perlu duduk dan menghitungnya. Jika perusahaan menghasilkan 100 juta dolar per tahun, seberapa besar sistem terdistribusinya harus berkembang, apakah mudah mendapatkan instance PostgreSQL yang bisa menangani beban itu, atau apakah sharding per klien sudah cukup. Jika memungkinkan, PostgreSQL sangat layak dipertimbangkan. Seratus hal kecil menjadi lebih mudah
Solusi SQL biasanya lebih sederhana, memakai sumber daya komputasi lebih sedikit, dan lebih mudah didukung secara operasional
Namun agar bisa berfungsi, Anda harus cukup memahami database untuk tahu bahwa fitur seperti
SELECT FOR UPDATE SKIP LOCKEDmemang ada sejak awal. Saat ini makin banyak engineer tumbuh di lingkungan tempat ORM berat menghalangi kemampuan DBMS yang sebenarnya, sehingga pengetahuan semacam ini menjadi cukup langkaSistem harus mampu menahan beban puncak, dan jika Anda tidak tahu puncaknya, Anda perlu memberi margin aman atau memasukkan cara untuk membuang pekerjaan atau menundanya saat diperlukan
Semuanya adalah trade-off, dan Anda hanya perlu mengoptimalkan hal yang memang perlu dioptimalkan; kemampuan menentukan apa yang termasuk di dalamnya adalah ciri engineer yang baik
Jika ini hal baru bagi Anda, berarti membaca HN selama seminggu pada jam kerja baru saja terbayar; layak ditulis di kertas dan ditempelkan ke kartu ATM Anda
Di beberapa proyek, saya memilih pendekatan yang lebih sederhana: memakai tabel biasa dan
SELECT FOR UPDATE SKIP LOCKED, yang langsung bisa digunakan dari ORM/query DSL framework di semua bahasahttps://www.pgcasts.com/episodes/the-skip-locked-feature-in-...
Ini bukan “skala web”, tetapi berdasarkan pengalaman saya, ia mudah diskalakan hingga ribuan background job
Saya menggunakan cara ini untuk pekerjaan di organisasi besar tanpa masalah. Tidak perlu deployment khusus atau infrastruktur baru; cukup jalankan beberapa worker thread di dalam aplikasi. Anda juga bisa menambahkan thread yang mereset pekerjaan yang terbengkalai
Namun selama 3 tahun, situasi seperti itu sebenarnya tidak pernah terjadi; semuanya berada di dalam
try/catch, jadi jika gagal akan dimasukkan kembali ke queue, dan aplikasi Java-nya juga sangat stabildelete from taskwhere task_id in( select task_idfrom taskorder by random() -- use tablesample for better performancefor updateskip lockedlimit 1)returning task_id, task_type, params::jsonb as params[1] https://taylor.town/pg-task
Anda menyebut “ribuan background job”, tetapi queue biasanya harus dilihat berdasarkan Hukum Little, dan yang perlu disebut adalah rasio seperti rata-rata laju masuk pekerjaan per detik dan rata-rata durasi pekerjaan. Jumlah mentah saja tidak terlalu bermakna
Pada awalnya,
UPDATE ... SETyang naif pun bisa berjalan, tetapi ia mengambil terlalu banyak lock. Anda bisa memakai subquerySELECTdalamUPDATE, atau mengefisienkan lock pengambilan denganSELECT FOR UPDATE SKIP LOCKED, tetapi pada akhirnya query pengambilan saling memblokir lock satu sama lain dan queue bisa berhentiSaat itu Anda bisa mematikan pemasukan pekerjaan untuk memberi DB ruang bernapas, tetapi kehilangan pemasukan tersebut menyebabkan kehilangan data, dan biasanya masalah intinya adalah proses pengambilan saling memblokir
Anda juga bisa buru-buru melakukan sharding pada tabel pekerjaan untuk menghindari lock, tetapi ini rapuh untuk didistribusikan ke banyak worker dan bisa berujung pada kehilangan data. Anda bisa membuang sebagian pekerjaan secara acak, tetapi tentu saja itu kehilangan data
Pilihan-pilihan seperti ini sangat menegangkan saat sistem sedang berjalan, dan pemulihannya juga sangat sulit tanpa mendesain ulang dari nol. Kecuali Anda hanya punya beberapa pelanggan dan yakin selamanya hanya akan berada di level puluhan pekerjaan per detik, setelah mengalami situasi seperti ini sendiri, saya memilih teknologi queue sungguhan dibanding database jika memungkinkan
Saya sering melihat kritik seperti “para engineer meniru infrastruktur FAANG agar terlihat keren, padahal kebutuhannya sama sekali berbeda”, tetapi menurut saya sebagian besarnya adalah masalah pengetahuan dan dokumentasi
Jika ingin mengikuti FAANG atau startup lain untuk membuat arsitektur berbasis antrean yang dapat diskalakan tanpa batas, ada puluhan panduan, tutorial, dan whitepaper berkualitas tinggi yang memungkinkan Anda menyiapkan solusi yang skalabel seperti Redis atau SQS dalam beberapa jam
Biaya pemeliharaannya memang lebih tinggi, tetapi Anda bisa memulai dengan menyalin-tempel perintah, kode, dan konfigurasi dari sumber bereputasi
Sebaliknya, jika ingin memakai
NOTIFYPostgreSQL lalu mencari “SQLALchemy notify listen postgres”, yang muncul hanya beberapa pertanyaan Stack Overflow tanpa jawaban dan GitHub Gist tanpa konteksSaya benar-benar ingin mencoba pendekatan ini di proyek sampingan, tetapi tidak punya kelonggaran untuk menghabiskan 2–3 hari sendirian mencari tahu
Dari luar, pilihannya tampak seperti “sederhana tetapi tidak skalabel, yaitu hanya memakai PostgreSQL” versus “rumit tetapi skalabel, yaitu Redis/SQS dan sejenisnya”, sehingga seolah-olah saya memilih skalabilitas yang tidak diperlukan karena silau oleh teknologi keren dan FAANG
Namun jika panduan dan materi juga diperhitungkan, pilihan sebenarnya lebih dekat ke “rumit dan skalabilitasnya pun tidak terprediksi, karena saya tidak tahu cara implementasi dan jebakannya” versus “sederhana dan skalabel, cara yang memang dilakukan semua orang”. Dengan begitu, pilihan engineer yang mengikuti FAANG terlihat jauh lebih masuk akal
NOTIFY, cukup baca https://www.postgresql.org/docs/current/sql-notify.html, tidak perlu kemampuan pencarian khususMisalnya, dengan PostgreSQL yang bebannya rendah, migrasi skema, penambahan constraint baru, analitik, dan semacamnya hampir menjadi hal sepele
Jika memakai SQS, Cassandra, dan sebagainya, Anda memperoleh skalabilitas/ketersediaan, tetapi ketika menyadari desain awalnya tidak cocok, mengubahnya akan memakan waktu jauh lebih lama. Contohnya saat bisnis meminta menambahkan constraint seperti “pengguna tipe foo tidak boleh mengombinasikan nilai bar secara bersamaan”
Implementasinya mungkin saja dilakukan tanpa PostgreSQL, tetapi terutama bila perlu perubahan, itu tidak mudah atau sederhana
Karena itu, menurut saya lebih baik memakai PostgreSQL untuk menjaga fleksibilitas, lalu memakai hal lain di atas PostgreSQL ketika sudah tahu bahwa bagian tersebut tidak akan berubah. Tentu saja dalam kasus ini ada overhead infrastruktur dan pemeliharaan tambahan
Pada akhirnya selalu ada kompromi, dan kita harus tahu apa yang ditukar dengan apa, serta kapan
Menurut saya, tidak ideal jika semua orang mengimplementasikan sendiri worker background job kustom di dalam aplikasi, entah dengan backend PostgreSQL maupun antrean lain
Background job memiliki banyak nuansa dan detail implementasi yang mudah salah, sehingga biasanya lebih baik ditangani oleh library atau framework khusus yang lebih menyeluruh
Jika setiap aplikasi Rails tidak memiliki Sidekiq/Active Jobs dan masing-masing mengimplementasikan worker background kustom sendiri, kemungkinan besar aplikasi Rails akan punya reputasi reliabilitas yang jauh lebih buruk daripada sekarang
Pilih saja solusi yang memberi keuntungan terbesar tanpa terlalu menjauh dari tujuan utama
Saya pernah melihat startup yang para developernya menghabiskan sekitar 80% waktu untuk bergulat dengan tooling dan infrastruktur. Runway-nya tinggal 3 bulan, dan sekarang yang tersisa di ujungnya hanya lubang besar. Memikirkannya saja masih membuat saya bergidik
Rasanya belum ada penghormatan terhadap kompleksitas yang cukup
Kelemahan terbesar saat memakai PostgreSQL sebagai bus publish/subscribe bersama
LISTEN/NOTIFYadalahLISTENmerupakan fitur sesi, sehingga tidak cocok dengan connection pooling per statementJika memakai pendekatan ini, sebaiknya gunakan advisory lock. Lock eksplisit lain memberi beban lebih besar pada database, tetapi advisory lock sengaja dibuat sangat ringan
Contoh implementasi yang saya suka adalah que, yang telah di-port ke beberapa bahasa
NOTIFY/LISTENadalah karena ketika terjadi masalah, sulit didiagnosisBaru-baru ini pun ada masalah di mana setelah beberapa waktu semua
NOTIFY/LISTENberhenti, dan hanya bisa diselesaikan dengan me-restart database, sehingga kami harus berhenti menggunakannya https://dba.stackexchange.com/questions/325104/error-could-n...Bertahun-tahun lalu, Skype menggunakan PostgreSQL sebagai queue bersama sebuah plugin kecil untuk memproses semua CDR. Entah apakah masih dipakai sekarang, tetapi menurut standar 10 tahun lalu itu sudah “skala web”, dan sementara orang-orang di internet berdebat bahwa memakai database sebagai queue adalah antipattern, sistem itu berjalan baik-baik saja
Adanya transaksi itu cukup praktis
https://wiki.postgresql.org/wiki/SkyTools
Karena saya cukup banyak memakainya di pekerjaan, saya juga beberapa kali memberi presentasi tentang topik ini di Sydpy. Berguna kalau Anda sudah mengoperasikan dan mendukung PostgreSQL dengan baik
Namun kalau sekarang, sepertinya saya akan memakai queue khusus, dan akan menghindari RabbitMQ khususnya
Bahkan jika khawatir soal vendor lock-in, operasi dasar queue pada dasarnya kecil, hanya semacam push/pop, jadi relatif mudah juga menulisnya agar gampang dipindahkan bila perlu
Jika Anda memasukkan queue ke database hanya karena database sudah dioperasikan, logika itu adalah pedang bermata dua. Bukan sesuatu yang patut dirayakan, tetapi kekacauan queue kini bisa ikut menjatuhkan penyimpanan data utama
Salah satu keunggulan terbesar saat memakai PostgreSQL sebagai queue aplikasi adalah semua pekerjaan asinkron yang dijadwalkan mendapat manfaat dari transaksionalitas
Misalnya ada perubahan backend yang kompleks setelah pendaftaran pengguna, lalu setelah memasukkan pekerjaan pengiriman email, bagian berikutnya dalam transaksi yang sama gagal dan di-rollback; maka pekerjaan email itu sejak awal tidak akan masuk ke queue
Untuk email, jika menunggu konfirmasi pengiriman lalu gagal, Anda harus memilih apakah menggagalkan transaksi dan menerima kemungkinan email ganda, atau melanjutkan dan menerima kemungkinan email hilang
Keuntungan besarnya muncul pada jalur kode yang memodifikasi DB secara asinkron. Karena konsumsi pekerjaan dan pembaruan DB berada dalam transaksi yang sama, semantik tepat sekali dapat ditangani sepenuhnya secara transaksional
Di PostgreSQL, saya menaruh tabel log transaksi yang berisi event yang terpicu dan
pg_current_xact_id()dari transaksi tersebut. Bisa juga memakaixminbawaan baris, tetapi harus memperhatikan transaction wraparound. Penyisipan ke baris ini memicuNOTIFYSebuah proses latar belakang berjalan berulang; dari tabel transaksi ia memilih semua baris dengan ID transaksi di antara
xmindari eksekusi sebelumnya danpg_snapshot_xmin(pg_current_snapshot())saat ini. Event-event itu dipetakan menjadi pekerjaan dan dikirim ke SQS, laluxmindicatat dan proses menungguNOTIFYberikutnya denganLISTENPada queue PostgreSQL, benar bahwa jika setelah memasukkan pekerjaan pengiriman email transaksi kemudian gagal, email tidak akan masuk queue
Kode database yang memang harus sepenuhnya terpisah layak dipisahkan ke transaksi yang berbeda. Sebaliknya, jika pengguna belum dibuat di DB, Anda mungkin juga tidak ingin mengirim email pendaftaran, jadi tergantung situasinya
Dengan queue berbasis Redis atau pada dasarnya queue lain mana pun, Anda akan segera menemui situasi ketika pekerjaan yang mengasumsikan record database sudah ada dijalankan sebelum transaksi di-commit. Kode untuk memperbaiki ini biasanya canggung dan rumit
Hal yang saya sukai dari Kafka adalah ia sekadar log append-only, dan klien pada dasarnya hanya memegang offset
Secara konsep sangat sederhana untuk dipahami, persisten, dan cukup tangguh terhadap kegagalan, karena bisa kembali ke offset mana pun dan membaca ulang
Sayangnya, karena sifat terdistribusinya, Kafka membawa kompleksitas yang cukup besar sehingga untuk sebagian besar use case akhirnya tidak sepadan
Secara pribadi, saya ingin ada sesuatu yang mirip tetapi lebih mudah dioperasikan. Di satu node, seharusnya bisa menangani ratusan, mungkin ribuan event per detik, dan tanpa kompleksitas distribusi itu akan cukup bagus
Secara teori ini juga bisa dilakukan dengan PostgreSQL, cukup jangan pernah menghapus baris. Mungkin itu jawabannya
Jika tidak membutuhkan seluruh fitur seperti consumer group dan partition, konfigurasi consumer juga akan jauh lebih sederhana
Di Windmill kami memakai pendekatan persis ini. Windmill adalah alternatif Retool open source sekaligus alat yang lebih mirip Airflow modern, dan kami menjalankan benchmark setiap hari
Jika satu worker Windmill dan PostgreSQL dijalankan sebagai container di instance GitHub CI yang biasa saja, benchmark memproses 1.200 pekerjaan per detik. Jika worker ditambah, skalanya stabil hingga 5.000 pekerjaan per detik
Kami sedang mempertimbangkan penggunaan Citus untuk menembus batas 5.000 pekerjaan per detik pada instance multitenant
https://github.com/windmill-labs/windmill/tree/benchmarks
Pada masa ketika volumenya sekitar 10 pesan per detik, kami memakai PostgreSQL untuk sebagian antrean, dan memang cukup bisa diskalakan. Namun jujur saja, menyiapkan SQS atau stack antrean lain di AWS, GCP, atau Azure itu sangat mudah, dibuat khusus untuk tujuan tersebut, dan hal seperti DLQ juga sudah bawaan
Saya tidak tahu mengapa harus memilih jalan ini sambil khawatir sistem itu runtuh lalu ikut memengaruhi kondisi DB lainnya
Saya suka prinsip “pakai alat yang paling sederhana”, tetapi kadang para engineer tampaknya melangkah terlalu jauh, sampai yang tersisa hanya alat paling bodoh dengan catatan peringatan yang samar, padahal alternatif arus utama relatif murah dan sederhana
Jika status pekerjaan disimpan di DB, status itu bisa di-query dengan nyaman. Meski tidak selalu menunjukkan status sebenarnya secara akurat, ini membantu saat menganalisis insiden operasional. Terutama karena kebanyakan antrean pekerjaan akan begitu saja menghapus record yang sudah diproses
Dan jika semua pekerjaan latar belakang dibuat idempoten, pendekatan seperti “mengirim pesan ke antrean pekerjaan agar pekerjaan ini diproses” hampir selalu aman
Jika hanya bergantung pada message queue, sering kali sulit mengetahui apa yang terjadi saat muncul masalah performa. Misalnya, RabbitMQ bisa memberi tahu ukuran antrean, tetapi kemampuan untuk memeriksa data internalnya hampir tidak ada atau sangat terbatas
Sebagian perangkat lunak bisa diperkirakan tidak akan pernah melampaui kemampuan PostgreSQL, dan kalaupun melampauinya, bisa dibuat agar mudah dipindahkan ke layanan lain
Dan mungkin juga ada keinginan untuk membuat sistem pekerjaan yang memiliki transaksi secara sederhana di dalam PostgreSQL
Kami menggunakan Oban dari Elixir untuk memproses ratusan ribu hingga jutaan pekerjaan setiap hari di dalam PostgreSQL
Adanya semantik transaksi di sekitar pekerjaan latar belakang—misalnya hanya menjadwalkan email ketika transaksi berhasil—sangatlah praktis
Perlu sedikit tuning pada
autovacuum, tetapi setelah dibereskan, ini sangat cocok untuk kami