Pada chapter ini kita akan praktek penerapan salah satu teknik concurrent programming di Go yaitu worker pool, dikombinasikan dengan database connection pool, untuk membaca 1 juta rows data dari sebuah file csv untuk kemudian di-insert-kan ke mysql server. Pada bagian insert data kita terapkan mekanisme failover, jadi ketika ada operasi insert gagal, maka akan otomatis di recover dan di retry. Jadi idealnya di akhir, semua data, sejumlah satu juta, akan berhasil di-insert. D.1.1. Penjelasan• Worker PoolWorker pool adalah teknik manajemen goroutine dalam concurrent programming pada Go. Sejumlah worker dijalankan dan masing-masing memiliki tugas yang sama yaitu menyelesaikan sejumlah jobs. Dengan metode worker pool ini, maka penggunaan memory dan performansi program akan bisa optimal. • Database Connection PoolConnection pool adalah metode untuk manajemen sejumlah koneksi database, agar bisa digunakan secara optimal. Connection pool sangat penting dalam kasus operasi data yang berhubungan dengan database yang di mana concurrent programming diterapkan. Karena pada concurrent programming, beberapa proses akan berjalan bersamaan, maka penggunaan 1 koneksi db akan menghambat proses tersebut. Perlu ada beberapa koneksi database, agar goroutine tidak rebutan objek koneksi database. • FailoverFailover merupakan mekanisme backup ketika sebuah proses gagal. Pada konteks ini, failover mengarah ke proses untuk me-retry operasi insert ketika gagal. D.1.2. PersiapanFile majestic-million-csv digunakan sebagai bahan dalam praktek. File tersebut gratis dengan lisensi CCA3. Isinya adalah list dari top website berjumlah 1 juta. Silakan download file nya di sini http://downloads.majestic.com/majestic_million.csv. Setelah itu siapkan My SQL database server, create database dan sebuah tabel di dalamnya dengan nama domain.
Setelah itu buat project baru, dan sebuah file Karena di contoh ini saya menggunakan My SQL, maka perlu untuk go get driver RDBMS ini untuk go.
Jika pembaca ingin menggunakan driver lain, juga silakan. D.1.3. Praktek• Definisi KonstantaAda beberapa konstanta yang perlu dipersiapkan. Pertama connection string untuk komunikasi ke database server. Sesuaikan value nya dengan yang dipergunakan.
Lalu jumlah koneksi idle yang diperbolehkan, kita set saja 4, karena nantinya semua connection yg di create akan sibuk untuk bekerja meng-insert data.
Jumlah maksimum koneksi database dalam pool.
Jumlah worker yang akan bekerja untuk menjalankan job.
Path dari file CSV. Karena file berada satu level dengan
Terakhir, siapkan variabel untuk menampung data header dari pembacaan CSV nanti.
• Fungsi Buka Koneksi DatabaseBuat fungsi untuk buka koneksi database, yg dikembalikan objek database kembalian fungsi Jangan lupa set nilai O iya, untuk yang tidak menggunakan mysql, maka sesuaikan saja nilai argument pertama statement
O iya jangan lupa untuk import driver nya.
• Fungsi Baca CSVBuka file CSV, lalu gunakan objek file untuk membuat objek CSV reader baru.
• Fungsi Menjalankan WorkersOk, sekarang kita mulai masuk ke aspek konkurensi dari pembahasan
ini. Siapkan fungsi yang isinya men-dispatch beberapa goroutine sejumlah Tiap-tiap goroutine tersebut adalah worker atau pekerja, yang tugasnya nanti akan meng-insert data ke database. Saat aplikasi dijalankan, sejumlah 100 worker akan berlomba-lomba menyelesaikan job insert data sejumlah 1 juta data. 1 job adalah 1 data, maka rata-rata setiap worker akan menyelesaikan operasi insert sekitar 10k. Tapi ini jelasnya tidak pasti karena worker akan berkompetisi dalam penyelesaian job, jadi sangat besar kemungkinan akan ada job yang menyelesaikan lebih dari 10k jobs, ataupun yg di bawah 10k jobs.
Bisa dilihat dalam fungsi di atas, di dalam goroutine/worker, isi channel jobs (yang berupa data dari proses pembacaan CSV), didistribusikan ke worker, ke goroutine. Fungsi Idealnya di akhir aplikasi akan terjadi pemanggilan • Fungsi Baca CSV dan Pengiriman Jobs ke WorkerProses pembacaan CSV, apapun metodenya pasti yang dijalankan adalah membaca data dari line ke line dari baris paling bawah.
Data dibaca dalam perulangan per baris. Pada pembacaan pertama,
rows akan ditampung ke variabel Setelah proses baca data selesai, channel di close. Karena pengiriman dan penerimaan data pada channel bersifat synchronous untuk unbuffered channel. Jadi aman untuk berasumsi bahwa ketika semua data berhasil dikirim, maka semua data tersebut juga berhasil diterima. Jika blok kode perulangan dalam fungsi di atas selesai, maka sudah tidak ada lagi operasi kirim terima data, maka kita close channelnya. • Fungsi Insert Data ke Database
Pada kode di atas bisa dilihat bahwa kode insert dibungkus dalam IIFE dalam sebuah perulangan. Kenapa butuh perulangan? keyword Nah jadi ketika operasi insert di atas gagal, maka error tetap di tampilkan tapi kemudian diulang kembali insert data yang gagal tadi, hingga sukses. O iya, mengenai kode untuk manajemen db connection poll mana ya? sepertinya tidak ada. Yups, memang tidak ada. As per Go official documentation untuk package
Btw, di atas juga ada satu fungsi lagi, • Fungsi MainTerakhir, panggil semua fungsi yang sudah dibuat pada main.
Di akhir fungsi main ditambahkan log untuk benchmark performa. D.1.4. Eksekusi ProgramOk, sekarang mari kita coba eksekusi program-nya. Nah, bisa dilihat operasi insert selesai dalam waktu sekitar 1 menitan. Saya menggunakan laptop dengan spek berikut untuk run program:
Kalau diperhatikan, hanya 25.8% utilisasi CPU, dan hanya 12MB saja resource RAM yang dibutuhkan. Di Task Manager CPU usage nya 100% karena My SQL server di lokal saya benar-benar bekerja keras untuk menjalankan operasi insert.
Kalau dibandingkan dengan operasi insert data secara sekuensial, yang tanpa worker pool dan tanpa db connection pool, memakan waktu hingga 20 MENIT!. Metode pada chapter ini jauh lebih cepat. Praktek pada chapter ini sifatnya adalah POC, jadi sangat mungkin diperlukan penyesuaian untuk kasus nyata. Kode di atas sebenarnya juga masih bisa di optimize lagi dari banyak sisi.
|