Menyimpan acara frekuensi tinggi ke basis data batasan koneksi


13

Kami punya situasi di mana saya harus berurusan dengan gelombang besar peristiwa yang datang ke server kami, sekitar 1000 peristiwa per detik, rata-rata (puncaknya bisa ~ 2000).

Masalah

Sistem kami dihosting di Heroku dan menggunakan Heroku Postgres DB yang relatif mahal , yang memungkinkan maksimum 500 DB koneksi. Kami menggunakan pooling koneksi untuk terhubung dari server ke DB.

Acara datang lebih cepat daripada kelompok koneksi DB yang bisa menangani

Masalah yang kami miliki adalah bahwa acara datang lebih cepat daripada yang bisa ditangani oleh kumpulan koneksi. Pada saat satu koneksi telah menyelesaikan jaringan bolak-balik dari server ke DB, sehingga dapat dilepaskan kembali ke kolam, lebih dari nperistiwa tambahan yang masuk.

Akhirnya acara menumpuk, menunggu untuk diselamatkan dan karena tidak ada koneksi yang tersedia di kolam, mereka kehabisan waktu dan seluruh sistem dibuat non-operasional.

Kami telah memecahkan keadaan darurat dengan memancarkan peristiwa frekuensi tinggi yang menyinggung dengan kecepatan lebih lambat dari klien, tetapi kami masih ingin tahu bagaimana menangani skenario ini jika kami perlu menangani peristiwa frekuensi tinggi itu.

Kendala

Klien lain mungkin ingin membaca acara secara bersamaan

Klien lain terus menerus meminta untuk membaca semua acara dengan kunci tertentu, bahkan jika mereka belum disimpan dalam DB.

Klien dapat meminta GET api/v1/events?clientId=1dan mendapatkan semua acara yang dikirim oleh klien 1, bahkan jika acara tersebut belum selesai menyimpan dalam DB dulu.

Apakah ada contoh "ruang kelas" tentang cara menangani ini?

Solusi yang memungkinkan

Enqueue acara di server kami

Kami dapat melakukan enqueue acara di server (dengan antrian memiliki konkurensi maksimum 400 sehingga kumpulan koneksi tidak habis).

Ini ide yang buruk karena:

  • Ini akan memakan memori server yang tersedia. Acara enqueued yang ditumpuk akan mengkonsumsi RAM dalam jumlah besar.
  • Server kami restart sekali setiap 24 jam . Ini adalah batasan keras yang dikenakan oleh Heroku. Server dapat memulai kembali sementara acara enqueued menyebabkan kita kehilangan acara enqueued.
  • Ini memperkenalkan status di server, sehingga merusak skalabilitas. Jika kami memiliki pengaturan multi-server dan klien ingin membaca semua peristiwa yang diselamatkan + enqueued, kami tidak akan tahu di server mana acara enqueued hidup.

Gunakan antrian pesan terpisah

Saya berasumsi kita bisa menggunakan antrian pesan, (seperti RabbitMQ ?), Di mana kita memompa pesan di dalamnya dan di ujung lain ada server lain yang hanya berurusan dengan menyimpan acara di DB.

Saya tidak yakin apakah antrian pesan memungkinkan kueri acara enqueued (yang belum disimpan) jadi jika klien lain ingin membaca pesan klien lain, saya bisa mendapatkan pesan yang disimpan dari DB dan pesan yang tertunda dari antrian dan menyatukannya sehingga saya dapat mengirimnya kembali ke klien baca-permintaan.

Gunakan beberapa basis data, masing-masing menyimpan sebagian pesan dengan server pusat koordinator DB untuk mengelolanya

Solusi lain yang kami miliki adalah menggunakan banyak basis data, dengan pusat "koordinator DB / penyeimbang beban". Setelah menerima suatu acara, koordinator ini akan memilih salah satu database untuk menulis pesan. Ini seharusnya memungkinkan kita untuk menggunakan banyak basis data Heroku sehingga menaikkan batas koneksi ke 500 x jumlah basis data.

Setelah kueri baca, koordinator ini dapat mengeluarkan SELECTkueri ke setiap basis data, menggabungkan semua hasil dan mengirimkannya kembali ke klien yang meminta baca.

Ini ide yang buruk karena:

  • Gagasan ini terdengar seperti ... ahem .. over-engineering? Akan menjadi mimpi buruk untuk dikelola juga (cadangan dll.). Ini rumit untuk dibangun dan dipelihara dan kecuali jika benar-benar diperlukan itu terdengar seperti pelanggaran KISS .
  • Itu mengorbankan Konsistensi . Melakukan transaksi lintas banyak DB tidak perlu dilakukan jika kita menggunakan ide ini.

3
Di mana kemacetan Anda? Anda menyebutkan kumpulan koneksi Anda, tetapi itu hanya memengaruhi paralelisme, bukan kecepatan per insert. Jika Anda memiliki 500 koneksi dan misalnya 2000QPS, ini akan berfungsi dengan baik jika setiap kueri selesai dalam 250ms yang merupakan waktu yang lama. Mengapa itu di atas 15 ms? Perhatikan juga bahwa dengan menggunakan PaaS Anda memberikan peluang optimisasi yang signifikan, seperti meningkatkan skala perangkat keras basis data atau menggunakan replika baca untuk mengurangi beban pada basis data primer. Heroku tidak layak kecuali penyebaran adalah masalah terbesar Anda.
amon

@amon Kemacetan memang kolam koneksi. Saya sudah menjalankan ANALYZEquery sendiri dan mereka tidak masalah. Saya juga telah membangun prototipe untuk menguji hipotesis kumpulan koneksi dan memverifikasi bahwa ini memang masalahnya. Basis data dan server itu sendiri hidup pada mesin yang berbeda maka latensi. Juga, kami tidak ingin melepaskan Heroku kecuali benar-benar diperlukan, tidak khawatir tentang penyebaran adalah nilai tambah yang besar bagi kami.
Nik Kyriakides

1
Yang sedang berkata, saya mengerti bahwa ada optimasi mikro yang bisa saya lakukan yang akan membantu saya memecahkan masalah saat ini . Saya ingin tahu apakah ada solusi arsitektur yang dapat diskalakan untuk masalah saya.
Nik Kyriakides

3
Bagaimana tepatnya Anda memverifikasi bahwa kumpulan koneksi adalah masalah? @amon benar dalam perhitungannya. Coba keluarkan select nullpada 500 koneksi. Saya yakin Anda akan menemukan bahwa kolam koneksi bukan masalah di sana.
usr

1
Jika pilih null bermasalah maka Anda mungkin benar. Meskipun akan menarik di mana semua waktu itu dihabiskan. Tidak ada jaringan yang lambat.
usr

Jawaban:


9

Input stream

Tidak jelas apakah 1000 acara / detik Anda mewakili puncak atau jika ini adalah beban berkelanjutan:

  • jika ini adalah puncak, Anda bisa menggunakan antrian pesan sebagai buffer untuk menyebarkan beban pada server DB lebih lama;
  • jika memuat konstan, antrian pesan saja tidak cukup, karena server DB tidak akan pernah bisa mengejar ketinggalan. Maka Anda harus berpikir tentang database terdistribusi.

Solusi yang diajukan

Secara intuitif, dalam kedua kasus ini, saya akan memilih aliran acara berbasis Kafka :

  • Semua acara diterbitkan secara sistematis pada topik kafka
  • Seorang konsumen akan berlangganan ke acara dan menyimpannya ke database.
  • Prosesor permintaan akan menangani permintaan dari klien dan permintaan DB.

Ini sangat scalable di semua tingkatan:

  • Jika server DB adalah hambatan, cukup tambahkan beberapa konsumen. Masing-masing dapat berlangganan ke topik, dan menulis ke server DB yang berbeda. Namun, jika distribusi terjadi secara acak di server DB, prosesor kueri tidak akan dapat memprediksi server DB untuk mengambil dan harus meminta beberapa server DB. Ini dapat menyebabkan kemacetan baru di sisi permintaan.
  • Oleh karena itu, skema distribusi DB dapat diantisipasi dengan mengatur aliran peristiwa ke dalam beberapa topik (misalnya, menggunakan kelompok kunci atau properti, untuk mempartisi DB sesuai dengan logika yang dapat diprediksi).
  • Jika satu server pesan tidak cukup untuk menangani membanjirnya peristiwa input, Anda dapat menambahkan partisi kafka untuk mendistribusikan topik kafka di beberapa server fisik.

Menawarkan acara yang belum ditulis dalam DB kepada klien

Anda ingin klien Anda bisa mendapatkan akses juga ke informasi yang masih dalam pipa dan belum ditulis ke DB. Ini sedikit lebih rumit.

Opsi 1: Menggunakan cache untuk melengkapi permintaan db

Saya belum menganalisis secara mendalam, tetapi gagasan pertama yang muncul di benak saya adalah membuat pemroses kueri menjadi konsumen topik kafka, tetapi dalam kelompok konsumen kafka yang berbeda . Pemroses permintaan kemudian akan menerima semua pesan yang akan diterima oleh penulis DB, tetapi secara independen. Itu kemudian bisa menyimpannya dalam cache lokal. Kueri kemudian akan berjalan pada DB + cache (+ penghapusan duplikat).

Desainnya kemudian akan terlihat seperti:

masukkan deskripsi gambar di sini

Skalabilitas lapisan kueri ini dapat dicapai dengan menambahkan lebih banyak prosesor kueri (masing-masing dalam kelompok konsumennya sendiri).

Opsi 2: desain API ganda

Pendekatan IMHO yang lebih baik adalah menawarkan API ganda (gunakan mekanisme kelompok konsumen terpisah):

  • API kueri untuk mengakses acara di DB dan / atau membuat analitik
  • API streaming yang hanya meneruskan pesan langsung dari topik

Keuntungannya, Anda membiarkan klien memutuskan apa yang menarik. Ini dapat menghindari bahwa Anda secara sistematis menggabungkan data DB dengan data yang baru diuangkan, ketika klien hanya tertarik pada peristiwa baru yang masuk. Jika penggabungan halus antara acara baru dan yang diarsipkan benar-benar diperlukan, maka klien harus mengaturnya.

Varian

Saya mengusulkan kafka karena dirancang untuk volume yang sangat tinggi dengan pesan persisten sehingga Anda dapat me-restart server jika diperlukan.

Anda bisa membangun arsitektur yang sama dengan RabbitMQ. Namun jika Anda perlu antrian terus-menerus, ini dapat menurunkan kinerja . Juga, sejauh yang saya tahu, satu-satunya cara untuk mencapai konsumsi paralel dari pesan yang sama oleh beberapa pembaca (misalnya penulis + cache) dengan RabbitMQ adalah dengan mengkloning antrian . Jadi skalabilitas yang lebih tinggi mungkin datang dengan harga yang lebih tinggi.


Bintang; Apa yang Anda maksud dengana distributed database (for example using a specialization of the server by group of keys) ? Juga mengapa Kafka bukan RabbitMQ? Apakah ada alasan tertentu untuk memilih satu dari yang lain?
Nik Kyriakides

@NicholasKyriakides Terima kasih! 1) Saya hanya memikirkan beberapa server database independen tetapi dengan skema partisi yang jelas (kunci, geografi, dll.) Yang dapat digunakan untuk mengirim perintah secara efektif. 2) Secara intuitif , mungkin karena Kafka dirancang untuk sangat throughput yang tinggi dengan pesan persisten perlu me-restart server Anda?). Saya tidak yakin bahwa RabbitMQ fleksibel untuk skenario terdistribusi, dan antrian persisten menurunkan kinerja
Christophe

Untuk 1) Jadi ini sangat mirip dengan Use multiple databaseside saya tetapi Anda mengatakan saya tidak boleh hanya secara acak (atau round-robin) mendistribusikan pesan ke setiap database. Baik?
Nik Kyriakides

Iya. Pikiran pertama saya adalah untuk tidak pergi untuk distribusi acak karena mungkin meningkatkan beban pemrosesan untuk permintaan (kebanyakan permintaan dari beberapa DB beberapa waktu). Anda juga dapat mempertimbangkan mesin DB yang didistribusikan (egIgnite?). Tetapi untuk membuat pilihan berdasarkan informasi apa pun membutuhkan pemahaman yang baik tentang pola penggunaan DB (apa lagi yang ada di db, seberapa sering ditanya, pertanyaan seperti apa, apakah ada kendala transaksional di luar peristiwa individu, dll ...).
Christophe

3
Hanya ingin mengatakan bahwa meskipun kafka dapat memberikan throughput yang sangat tinggi, itu mungkin melebihi kebutuhan kebanyakan orang. Saya menemukan bahwa berurusan dengan kafka dan API-nya adalah kesalahan besar bagi kami. RabbitMQ bukan bungkuk dan memiliki antarmuka yang Anda harapkan dari MQ
imel96

11

Dugaan saya adalah bahwa Anda perlu mengeksplorasi lebih hati-hati suatu pendekatan yang telah Anda tolak

  • Enqueue acara di server kami

Saran saya adalah mulai membaca berbagai artikel yang diterbitkan tentang arsitektur LMAX . Mereka berhasil membuat batching volume tinggi berfungsi untuk kasus penggunaan mereka, dan dimungkinkan untuk membuat trade off Anda terlihat lebih seperti milik mereka.

Juga, Anda mungkin ingin melihat apakah Anda bisa mendapatkan bacaan keluar dari jalan - idealnya Anda ingin dapat skala mereka secara independen dari tulisan. Itu mungkin berarti melihat ke CQRS (perintah segregasi tanggung jawab permintaan).

Server dapat memulai kembali sementara acara enqueued menyebabkan kita kehilangan acara enqueued.

Dalam sistem terdistribusi, saya pikir Anda bisa cukup yakin bahwa pesan akan hilang. Anda mungkin dapat mengurangi beberapa dampak dari itu dengan bersikap bijaksana tentang hambatan urutan Anda (misalnya - memastikan bahwa penulisan ke penyimpanan tahan lama terjadi - sebelum acara dibagikan di luar sistem).

  • Gunakan beberapa basis data, masing-masing menyimpan sebagian pesan dengan server pusat koordinator DB untuk mengelolanya

Mungkin - saya akan lebih cenderung melihat batas bisnis Anda untuk melihat apakah ada tempat alami untuk membuang data.

Ada kasus di mana kehilangan data merupakan tradeoff yang dapat diterima?

Yah, saya kira mungkin ada, tapi itu bukan tujuan saya. Intinya adalah bahwa desain harus dibangun ke dalamnya kekuatan yang dibutuhkan untuk maju dalam menghadapi kehilangan pesan.

Apa ini sering terlihat adalah model berbasis tarik dengan pemberitahuan. Penyedia menulis pesan ke toko tahan lama yang dipesan. Konsumen menarik pesan dari toko, melacak tanda airnya sendiri. Notifikasi push digunakan sebagai perangkat pengurang latensi - tetapi jika notifikasi hilang, pesan masih diambil (akhirnya) karena konsumen menarik jadwal reguler (perbedaannya adalah jika notifikasi diterima, tarikan terjadi lebih cepat ).

Lihat Perpesanan yang Andal Tanpa Transaksi Terdistribusi, oleh Udi Dahan (sudah dirujuk oleh Andy ) dan Data Polyglot oleh Greg Young.


In a distributed system, I think you can be pretty confident that messages are going to get lost. Betulkah? Ada kasus di mana kehilangan data merupakan tradeoff yang dapat diterima? Saya mendapat kesan bahwa kehilangan data = kegagalan.
Nik Kyriakides

1
@NicholasKyriakides, biasanya tidak dapat diterima, oleh karena itu OP menyarankan kemungkinan untuk menulis ke toko yang tahan lama sebelum memancarkan acara. Lihat artikel ini dan video ini oleh Udi Dahan di mana ia membahas masalah ini dengan lebih rinci.
Andy

6

Jika saya mengerti benar aliran saat ini adalah:

  1. Terima dan acara (saya asumsikan melalui HTTP?)
  2. Minta koneksi dari kolam.
  3. Masukkan acara ke DB
  4. Lepaskan koneksi ke kolam.

Jika demikian saya pikir perubahan pertama pada desain akan berhenti memiliki Anda bahkan menangani koneksi kode kembali ke kolam pada setiap acara. Alih-alih membuat kumpulan thread / proses penyisipan yang 1-ke-1 dengan jumlah koneksi DB. Ini masing-masing akan memegang koneksi DB khusus.

Menggunakan semacam antrian konkuren, Anda kemudian memiliki utas ini menarik pesan dari antrian konkuren dan menyisipkannya. Secara teori mereka tidak perlu mengembalikan koneksi ke pool atau meminta yang baru tetapi Anda mungkin perlu membangun dalam penanganan jika koneksi memburuk. Mungkin paling mudah untuk membunuh utas / proses dan memulai yang baru.

Ini harus secara efektif menghilangkan overhead koneksi pool. Anda tentu saja harus mampu melakukan push setidaknya 1000 / koneksi acara per detik pada setiap koneksi. Anda mungkin ingin mencoba jumlah koneksi yang berbeda karena memiliki 500 koneksi yang bekerja pada tabel yang sama dapat membuat pertentangan pada DB tetapi itu pertanyaan yang sama sekali berbeda. Hal lain yang perlu dipertimbangkan adalah penggunaan sisipan batch yaitu setiap utas menarik sejumlah pesan dan mendorongnya sekaligus. Selain itu, hindari memiliki beberapa koneksi yang berusaha memperbarui baris yang sama.


5

Asumsi

Saya akan menganggap bahwa beban yang Anda gambarkan adalah konstan, karena itu adalah skenario yang lebih sulit untuk dipecahkan.

Saya juga akan menganggap Anda memiliki beberapa cara untuk menjalankan beban kerja yang terpicu dan lama di luar proses aplikasi web Anda.

Larutan

Dengan asumsi bahwa Anda telah mengidentifikasi dengan benar kemacetan Anda - latensi antara proses Anda dan database Postgres - itulah masalah utama yang harus dipecahkan. Solusi perlu memperhitungkan kendala konsistensi Anda dengan klien lain yang ingin membaca acara segera setelah dipraktikkan setelah mereka diterima.

Untuk mengatasi masalah latensi, Anda harus bekerja dengan cara yang meminimalkan jumlah latensi yang terjadi per peristiwa yang akan disimpan. Ini adalah hal utama yang perlu Anda capai jika Anda tidak mau atau tidak dapat mengubah perangkat keras . Karena Anda menggunakan layanan PaaS dan tidak memiliki kendali atas perangkat keras atau jaringan, satu-satunya cara untuk mengurangi latensi per peristiwa adalah dengan semacam penulisan peristiwa yang dikumpulkan.

Anda perlu menyimpan antrian acara secara lokal yang akan memerah dan ditulis secara berkala ke db Anda, baik setelah mencapai ukuran tertentu, atau setelah jumlah waktu yang telah berlalu. Suatu proses perlu memonitor antrian ini untuk memicu flush ke toko. Seharusnya ada banyak contoh tentang cara mengelola antrian serentak yang disiram secara berkala dalam bahasa pilihan Anda - Berikut adalah contoh dalam C # , dari wastafel batching berkala perpustakaan Serilog yang populer.

Jawaban SO ini menjelaskan cara tercepat untuk menyiram data di Postgres - walaupun itu akan meminta batching Anda menyimpan antrian pada disk, dan kemungkinan ada masalah yang harus dipecahkan di sana ketika disk Anda hilang saat reboot di Heroku.

Paksaan

Jawaban lain telah disebutkan CQRS , dan itu adalah pendekatan yang benar untuk menyelesaikan kendala. Anda ingin melembabkan model yang sudah dibaca karena setiap peristiwa diproses - pola Mediator dapat membantu merangkum acara dan mendistribusikannya ke beberapa penangan yang sedang diproses. Jadi satu penangan dapat menambahkan acara ke model baca Anda yang ada dalam memori yang dapat ditanyakan oleh klien, dan penangan lainnya dapat bertanggung jawab untuk mengantri acara tersebut pada penulisan batch akhirnya.

Manfaat utama CQRS adalah Anda memisahkan model baca dan tulis konseptual Anda - yang merupakan cara mewah untuk mengatakan Anda menulis ke dalam satu model, dan Anda membaca dari model lain yang sama sekali berbeda. Untuk mendapatkan manfaat skalabilitas dari CQRS, Anda biasanya ingin memastikan setiap model disimpan secara terpisah dengan cara yang optimal untuk pola penggunaannya. Dalam hal ini kita dapat menggunakan model baca agregat - misalnya, cache Redis, atau hanya dalam memori - untuk memastikan pembacaan kita cepat dan konsisten, sementara kita masih menggunakan database transaksional untuk menulis data.


3

Acara datang lebih cepat daripada kelompok koneksi DB yang bisa menangani

Ini adalah masalah jika setiap proses membutuhkan satu koneksi basis data. Sistem harus dirancang sehingga Anda memiliki kumpulan pekerja di mana setiap pekerja hanya membutuhkan satu koneksi basis data dan setiap pekerja dapat memproses beberapa peristiwa.

Antrian pesan dapat digunakan dengan desain itu, Anda memerlukan produsen pesan yang mendorong peristiwa ke antrian pesan dan pekerja (konsumen) memproses pesan dari antrian.

Klien lain mungkin ingin membaca acara secara bersamaan

Batasan ini hanya mungkin jika peristiwa disimpan dalam basis data tanpa pemrosesan apa pun (peristiwa mentah). Jika acara diproses sebelum disimpan dalam database, maka satu-satunya cara untuk mendapatkan acara adalah dari database.

Jika klien hanya ingin menanyakan acara mentah maka saya akan menyarankan menggunakan mesin pencari seperti Pencarian Elastis. Anda bahkan akan mendapatkan API permintaan / pencarian secara gratis.

Karena tampaknya meminta pertanyaan sebelum disimpan dalam basis data penting bagi Anda, solusi sederhana seperti Elastic Search seharusnya berfungsi. Anda pada dasarnya hanya menyimpan semua peristiwa di dalamnya dan tidak menduplikasi data yang sama dengan menyalinnya ke dalam basis data.

Pencarian Skala Elastis itu mudah, tetapi bahkan dengan konfigurasi dasar itu adalah pemain yang cukup tinggi.

Saat Anda membutuhkan pemrosesan, proses Anda bisa mendapatkan acara dari ES, memproses dan menyimpannya dalam database. Saya tidak tahu apa tingkat kinerja yang Anda butuhkan dari pemrosesan ini, tetapi itu akan sepenuhnya terpisah dari permintaan acara dari ES. Anda seharusnya tidak memiliki masalah koneksi, karena Anda dapat memiliki jumlah pekerja yang tetap dan masing-masing dengan satu koneksi database.


2

Peristiwa 1k atau 2k (5KB) per detik tidak terlalu banyak untuk basis data jika memiliki skema dan mesin penyimpanan yang sesuai. Seperti yang disarankan oleh @eddyce, seorang master dengan satu atau lebih budak dapat memisahkan permintaan baca dari melakukan penulisan. Menggunakan lebih sedikit koneksi DB akan memberi Anda throughput keseluruhan yang lebih baik.

Klien lain mungkin ingin membaca acara secara bersamaan

Untuk permintaan ini, mereka juga perlu membaca dari master db karena akan ada jeda replikasi pada slave yang sudah dibaca.

Saya telah menggunakan (Percona) MySQL dengan mesin TokuDB untuk penulisan volume yang sangat tinggi. Ada juga mesin MyRocks berdasarkan LSMtrees yang bagus untuk menulis banyak. Untuk kedua mesin ini dan kemungkinan juga PostgreSQL ada pengaturan untuk isolasi transaksi serta melakukan perilaku sinkronisasi yang secara dramatis dapat meningkatkan kapasitas menulis. Di masa lalu kami menerima hingga 1s data yang hilang yang dilaporkan ke klien db sebagai komitmen. Dalam kasus lain ada SSD yang didukung baterai untuk menghindari kehilangan.

Amazon RDS Aurora dalam citarasa MySQL diklaim memiliki throughput tulis 6x lebih tinggi dengan replikasi tanpa biaya (mirip dengan budak yang berbagi sistem file dengan master). Rasa Aurora PostgreSQL juga memiliki mekanisme replikasi canggih yang berbeda.


TBH setiap basis data yang dikelola dengan baik pada perangkat keras yang memadai harus dapat mengatasi beban ini. Masalah OP tampaknya bukan kinerja database tetapi latensi koneksi; Dugaan saya adalah Heroku karena penyedia PaaS menjual mereka contoh Postgres di wilayah AWS yang berbeda.
amon

1

Saya akan menjatuhkan heroku bersama-sama, yaitu, saya akan menjatuhkan pendekatan terpusat: banyak menulis bahwa memuncak koneksi kolam maksimum adalah salah satu alasan utama mengapa cluster db ditemukan, terutama karena Anda tidak memuat tulisan db (s) dengan permintaan baca yang dapat dilakukan oleh db lain di cluster, saya akan mencoba dengan topologi master-slave, apalagi - seperti orang lain yang telah disebutkan, memiliki instalasi db Anda sendiri akan memungkinkan untuk menyempurnakan keseluruhan sistem untuk memastikan waktu propagasi kueri akan ditangani dengan benar.

Semoga berhasil

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.