Saya pergi ke wawancara pekerjaan insinyur data. Pewawancara bertanya kepada saya. Dia memberi saya beberapa situasi dan meminta saya untuk mendesain aliran data untuk sistem itu. Saya memecahkannya tetapi dia tidak menyukai solusi saya dan saya gagal. Saya ingin tahu apakah Anda memiliki ide yang lebih baik bagaimana mengatasi tantangan itu.
Pertanyaannya adalah:
Sistem kami menerima empat aliran data. Data berisi id kendaraan, kecepatan, dan koordinasi geolokasi. Setiap kendaraan mengirimkan datanya satu menit sekali. Tidak ada hubungan antara aliran tertentu ke jalan atau kendaraan khusus atau apa pun. Ada fungsi yang menerima koordinasi dan mengembalikan nama bagian jalan. Kita perlu mengetahui kecepatan rata-rata per ruas jalan per 5 menit. Akhirnya kami ingin menulis hasilnya ke Kafka.
Jadi solusi saya adalah:
Pertama-tama, tulis semua data ke dalam cluster Kafka, ke dalam satu topik, dipartisi oleh 5-6 digit pertama garis bujur digabung menjadi 5-6 digit pertama garis bujur. Kemudian membaca data dengan Structured Streaming, menambahkan untuk setiap baris nama bagian jalan oleh koordinat (ada udf yang sudah ditentukan sebelumnya untuk itu), dan kemudian mengumpulkan data dengan nama bagian jalan.
Karena saya mempartisi data dalam Kafka dengan 5-6 digit pertama dari koordinasi, setelah menerjemahkan koordinat ke nama bagian, tidak perlu ada transfer banyak data ke partisi yang benar dan oleh karena itu saya dapat mengambil keuntungan dari operasi colesce () itu tidak memicu pengocokan penuh.
Kemudian menghitung kecepatan rata-rata per eksekutor.
Seluruh proses akan terjadi setiap 5 menit dan kami akan menulis data dalam mode Tambah ke wastafel Kafka akhir.
Jadi sekali lagi, pewawancara tidak menyukai solusi saya. Adakah yang bisa menyarankan cara memperbaikinya atau ide yang sama sekali berbeda dan lebih baik?
Jawaban:
Saya menemukan pertanyaan ini sangat menarik dan berpikir untuk mencobanya.
Saat saya mengevaluasi lebih lanjut, upaya Anda sendiri baik, kecuali yang berikut:
Jika Anda sudah memiliki metode untuk mendapatkan id / nama bagian jalan berdasarkan lintang dan bujur, mengapa tidak memanggil metode itu terlebih dahulu dan menggunakan id / nama bagian jalan untuk mempartisi data?
Dan setelah itu, semuanya cukup mudah, jadi topologi akan seperti itu
(Penjelasan lebih rinci dapat ditemukan dalam komentar dalam kode di bawah ini. Silakan tanyakan jika ada yang tidak jelas)
Saya telah menambahkan kode di akhir jawaban ini, harap dicatat bahwa alih-alih rata-rata, saya telah menggunakan jumlah karena lebih mudah untuk ditunjukkan. Dimungkinkan untuk melakukan rata-rata dengan menyimpan beberapa data tambahan.
Saya sudah merinci jawabannya dalam komentar. Berikut ini adalah diagram topologi yang dihasilkan dari kode (terima kasih kepada https://zz85.github.io/kafka-streams-viz/ )
Topologi:
sumber
Masalah seperti itu tampaknya sederhana dan solusi yang ditawarkan sudah masuk akal. Saya bertanya-tanya apakah pewawancara prihatin dengan desain dan kinerja solusi yang Anda fokuskan atau keakuratan hasilnya. Karena yang lain berfokus pada kode, desain, dan kinerja, saya akan mempertimbangkan akurasinya.
Solusi Streaming
Karena data mengalir, kami dapat memberikan perkiraan kasar tentang kecepatan rata-rata jalan. Estimasi ini akan membantu dalam mendeteksi kemacetan tetapi tidak aktif dalam menentukan batas kecepatan.
Solusi Batch
Estimasi ini akan dimatikan karena ukuran sampel kecil. Kami akan membutuhkan pemrosesan batch pada data bulan / kuartal / tahun penuh untuk lebih akurat menentukan batas kecepatan.
Baca data tahun dari danau data (atau Topik Kafka)
Terapkan UDF pada koordinat untuk mendapatkan nama jalan dan nama kota.
Hitung kecepatan rata-rata dengan sintaks seperti -
Berdasarkan batas kecepatan yang lebih akurat ini, kami dapat memprediksi lalu lintas lambat dalam aplikasi streaming.
sumber
Saya melihat beberapa masalah dengan strategi partisi Anda:
Ketika Anda mengatakan Anda akan mempartisi data Anda berdasarkan 5-6 digit pertama dari panjang lat, Anda tidak akan dapat menentukan jumlah partisi kafka sebelumnya. Anda akan memiliki data yang miring karena untuk beberapa ruas jalan Anda akan mengamati volume yang tinggi daripada yang lain.
Dan kombinasi kunci Anda tidak menjamin data bagian jalan yang sama di partisi yang sama dan karenanya Anda tidak dapat yakin bahwa tidak akan ada pengocokan.
Informasi yang diberikan IMO tidak cukup untuk merancang seluruh pipa data. Karena ketika mendesain pipa, bagaimana Anda mempartisi data Anda memainkan peran penting. Anda harus menanyakan lebih lanjut tentang data yang Anda terima seperti jumlah kendaraan, ukuran aliran data input, apakah jumlah aliran tetap atau dapatkah peningkatan di masa mendatang? Apakah aliran data input yang Anda terima adalah aliran kafka? Berapa banyak data yang Anda terima dalam 5 menit?
mapValues
danreduceByKey
bukannya groupBy. Lihat ini .sumber
mapValues
danreduceBy
memang milik RDD tingkat rendah tetapi masih akan berkinerja lebih baik dalam situasi ini karena pertama-tama akan menghitung agregat per partisi dan kemudian melakukan pengocokan.Masalah utama yang saya lihat dengan solusi ini adalah:
Saya akan mengatakan solusi yang perlu dilakukan: baca dari aliran Kafka -> UDF -> bagian jalan kelompok -> rata-rata -> tulis ke aliran Kafka.
sumber
Desain saya akan tergantung pada
Jika saya ingin mengukur jumlah hitungan, desainnya akan terlihat seperti ini
Kepedulian lintas pada desain ini -
Beberapa peningkatan praktis mungkin pada desain ini -
sumber