Desain arsitektur API untuk membaca cepat file teks dengan 150 m label unik
Asumsikan file teks dengan 150m catatan unik.
Setiap record memiliki dua kolom: (1) string dan (2) integer.
String adalah label unik, dan bilangan bulat adalah nilai label.
Satu-satunya kueri akan mengembalikan nilai integer untuk label tertentu.
Kami sedang menjelajahi beberapa arsitektur untuk mengekspos file teks ini sebagai API.
File teks ini dibuat ulang setiap 72 jam. ~ 90% dari data tetap sama di seluruh regenerasi, tetapi regenerasi ini dikontrol oleh pihak ketiga. Kami hanya mendapatkan file teks baru setiap 72 jam.
Kami menargetkan kinerja kueri 100 md - 500 md per baca.
Arsitektur 1
- Simpan file teks di disk. Buat kueri file teks. Kueri cache dalam memori.
- Kelebihan: Penerapannya sederhana. Mudah untuk memperbarui data.
- Kekurangan: Tidak elegan. Kueri baca yang tidak disimpan dalam cache lambat.
Arsitektur 2
- Parsing file teks menjadi database tradisional / NoSQL, dengan setiap baris diperlakukan sebagai record / dokumen database. Jalankan kueri terhadap database.
- Kelebihan: Sepertinya arsitektur standar.
- Kekurangan: Memperbarui catatan database 150m lambat dan tampaknya sia-sia, terutama karena ~ 90% catatan tetap sama.
Arsitektur 3
- Gunakan Redis atau database dalam memori untuk menyimpan file teks 5GB. Jalankan kueri terhadap database dalam memori.
- Kelebihan: Pertanyaan cepat. Mudah untuk memperbarui data.
- Kekurangan: Mahal.
Arsitektur 4
- Gunakan ElasticSearch untuk melakukan kueri rekaman.
- Kelebihan: ElasticSearch dirancang untuk pencarian.
- Kekurangan: ES mungkin berlebihan untuk pertanyaan sederhana seperti itu.
Pertanyaan:
Haruskah kita mempertimbangkan arsitektur lain, atau adakah pro / kontra yang kita abaikan?
Tantangan teknik ini tampaknya umum: arsitektur apa yang paling "standar" untuk menyeimbangkan biaya / kinerja saat mencoba menghasilkan pembacaan cepat terhadap penyimpanan data 150 juta rekaman yang berubah?
Jawaban
Secara umum, ini tampak seperti kasus klasik untuk aliran ETL: dapatkan file baru, Ekstrak data, Transformasikan ke format Anda dan Muat ke DB Anda. Beberapa catatan:
Hal penting untuk diingat adalah bahwa memuat dan membuat kueri adalah untuk operasi yang berbeda dan sama sekali tidak terkait. Satu pertanyaan adalah "bagaimana cara memuat file catatan 150m secara efisien setiap hari ke dalam penyimpanan data ketika 90% dari catatan adalah duplikat", dan yang lainnya adalah "bagaimana cara meminta penyimpanan kunci / nilai 150m-catatan secara efisien". Jawab kedua pertanyaan ini secara terpisah, karena keduanya independen.
Untuk pertanyaan pertama Anda, Anda khawatir bahwa memuat 90% record identik adalah pemborosan. Sudahkah Anda mengukur waktu yang dibutuhkan? Membaca catatan 150m dari file teks memerlukan beberapa detik , dan penyimpanan kunci / nilai yang baik harus dapat mengoptimalkan operasi UPDATE yang berlebihan. Cara lainnya, bedakan file baru dengan yang sebelumnya untuk membuat daftar perubahan aktual sebagai bagian dari aliran ETL Anda, lalu lanjutkan untuk memuat. Tentukan metrik untuk solusi ini (total waktu untuk membaca, diff, memuat, gangguan operasi kueri saat memuat, dll) sehingga Anda dapat mengevaluasi solusi Anda.
Untuk pertanyaan # 2, hindari menerapkan solusi ubahsuaian saat opsi siap pakai tersedia. ElasticSearch mungkin berlebihan karena Anda hanya menyimpan bilangan bulat yang dikunci, tetapi ada banyak penyimpanan kunci / nilai di luar sana yang akan memberi Anda kinerja yang baik untuk membaca termasuk caching memori yang didukung disk, caching MRU atau strategi caching yang berbeda tergantung pada penggunaan Anda, mungkin operasi UPDATE tanpa operasi yang disebutkan di atas, dan banyak lagi. Sekali lagi, seperti dalam pertanyaan # 1, tentukan metrik untuk sukses. Anda berkata "memuat 5GB ke dalam RAM itu mahal. Apakah itu? Berapa banyak RAM yang dimiliki server Anda? Anda mempertimbangkan untuk menyimpan kueri umum ke dalam cache. Apakah perlu? Seberapa cepat pembacaan yang tidak disimpan dalam cache? Ukur! Apakah Anda memerlukan strategi cache khusus seperti mendahului catatan terkait • Periksa pola penggunaan Anda.
Saya tidak bisa memberi tahu Anda apa pendekatan terbaik. Ada terlalu banyak variabel yang hanya Anda ketahui - anggaran dan pola penggunaan Anda, rencana masa depan untuk sistem dan potensi perluasan, hubungan dengan sumber data pihak ketiga (misalnya, dapatkah mereka diyakinkan untuk menghasilkan hanya diff, atau menambahkan stempel waktu / tag versi untuk catatan, dll). Yang dapat saya lakukan hanyalah menyarankan pola inti: memisahkan aliran penyerapan dari aliran kueri, menggunakan alat yang telah dicoba dan diuji, dan yang terpenting mengukur, mengukur, mengukur.
Anda dapat mempertimbangkan pendekatan yang dilakukan oleh DJBernstein ini CDB , yaitu:
cdb adalah paket yang cepat, andal, dan sederhana untuk membuat dan membaca database yang konstan. Struktur basis datanya menyediakan beberapa fitur:
Pencarian cepat: Pencarian yang berhasil dalam database besar biasanya hanya membutuhkan dua akses disk. Pencarian yang tidak berhasil hanya membutuhkan satu.
Overhead rendah: Database menggunakan 2.048 byte, ditambah 24 byte per record, ditambah ruang untuk kunci dan data.
Tidak ada batasan acak: cdb dapat menangani database apa pun hingga 4 gigabyte. Tidak ada batasan lain; catatan bahkan tidak harus masuk ke dalam memori. Basis data disimpan dalam format yang tidak tergantung mesin.
Penggantian database atomik yang cepat: cdbmake dapat menulis ulang seluruh database dua kali lipat lebih cepat daripada paket hashing lainnya.
Database dumps cepat: cdbdump mencetak isi database dalam format yang kompatibel dengan cdbmake.
cdb dirancang untuk digunakan dalam aplikasi penting seperti email. Penggantian database aman dari kerusakan sistem. Pembaca tidak perlu berhenti selama penulisan ulang.
Mungkin Anda menginginkan implementasi yang lebih modern, yang tidak memiliki batas 4GiB, seperti yang ini .