Dalam artikel sebelumnya, kami menyentuh beberapa aspek berbeda yang dapat mengarahkan Anda untuk memfaktorkan ulang kode Anda ke pendekatan berbasis layanan mikro. Salah satu aspek terakhir yang kami sentuh adalah pertanyaan tentang apa yang harus dilakukan dengan data Anda—dalam aplikasi perusahaan skala besar, itu sering merupakan masalah paling sulit dan salah satu yang layak untuk ditangani lebih mendalam. Apa yang telah kita lihat adalah, terkadang, sulit untuk menentukan kapan Anda melihat masalah pengodean atau masalah pemodelan data yang menyamar sebagai masalah pengodean.
Kami akan melihat beberapa kasus ini dan berbicara tentang pilihan pemodelan data yang dapat Anda buat untuk menyederhanakan dan meningkatkan kode yang difaktorkan ulang. Pertama-tama, kita perlu mengatasi apa yang sering menjadi pertanyaan awal yang diajukan oleh tim yang memfaktorkan ulang aplikasi perusahaan yang ada menjadi layanan mikro.
Tetap terinformasi tentang tren industri yang paling penting—dan menarik—tentang AI, otomatisasi, data, dan di luarnya dengan buletin Think. Lihat Pernyataan Privasi IBM®.
Jika aplikasi Anda seperti kebanyakan aplikasi yang kami lihat yang mulai difaktorkan kembali menjadi layanan mikro, kami mungkin dapat dengan aman mengasumsikan bahwa aplikasi tersebut bekerja dengan basis data relasional tunggal yang besar. Terlebih lagi, ada kemungkinan besar bahwa basis data ini adalah Oracle basis data—semua basis data relasional lainnya (DB2, SQL Server, Informix, atau bahkan basis data sumber terbuka seperti MySQL atau Postgres) membagi sisa bagian. Faktanya, pindah dari basis data relasional perusahaan (biasanya mahal) adalah salah satu manfaat yang sering dipromosikan untuk refactoring ke layanan mikro.
Sekarang, ada alasan yang sangat bagus untuk memilih jenis basis data lain— baik NewSQL atau NoSQL untuk banyak layanan mikro. Menghentikan penggunaan basis data relasional secara tiba-tiba biasanya bukan keputusan yang bijaksana. Sebaliknya, Anda mungkin ingin mempertimbangkan pendekatan yang lebih bertahap dalam mengubah basis data Anda, sama seperti kami menganjurkan pendekatan bertahap dalam melakukan refactoring padaJava Anda yang ada.
Sama seperti pendekatan inkremental untuk pengodean yang telah kami anjurkan, bagaimanapun, masalah terbesar dalam mengikuti pendekatan inkremental untuk refactoring basis data adalah memutuskan dari mana harus memulai. Keputusan pertama yang harus Anda buat setelah Anda memutuskan pendekatan inkremental adalah apakah Anda harus menggunakan satu basis data besar atau banyak basis data kecil. Sekarang, pada awalnya, ini terdengar seperti tidak masuk akal — tentu saja, Anda tidak menginginkan satu basis data besar, itulah yang Anda miliki di monolit Anda! Tapi mari kita jelaskan apa yang kita maksud terlebih dahulu.
Pada dasarnya, tempat untuk memulai adalah membuat perbedaan antara server basis data dan skema basis data. Bagi Anda yang akrab dengan basis data skala perusahaan seperti Oracle atau Db2, ini adalah sifat kedua karena perusahaan umumnya akan memiliki satu server Oracle besar (atau RAC, yang merupakan server besar yang terdiri dari banyak server yang lebih kecil) di mana beberapa tim akan meng-host basis data terpisah mereka sendiri (masing-masing diwakili oleh skema terpisah). Alasan ini dilakukan adalah karena lisensi sering dilakukan oleh CPU, dan perusahaan ingin memaksimalkan jumlah penggunaan yang bisa mereka dapatkan untuk uang mereka. Menempatkan beberapa tim bersama-sama dalam satu server besar adalah cara untuk melakukan ini. Bagi Anda yang lebih akrab dengan basis data sumber terbuka seperti MySQL atau PostgreSQL, ini sedikit kurang umum karena perbedaannya kurang sering dibutuhkan.
Ini penting karena ketika kita berbicara tentang membangun basis data untuk layanan mikro, penting bagi kita untuk mengurangi atau menghilangkan kopling di basis data — tetapi itu benar-benar berarti penggabungan pada tingkat skema basis data. Masalah muncul ketika Anda memiliki dua layanan mikro berbeda yang menggunakan informasi yang sama—tabel yang sama dalam skema yang sama. Anda melihat apa yang kami maksud ketika Anda melihat Gambar 1.
Basis data yang setara dengan aplikasi monolitik (alias “Big Ball of Mud,” di mana semuanya terhubung ke yang lain) memiliki satu skema besar yang menghubungkan setiap tabel bersama-sama. Kapan pun hal itu terjadi, jumlah upaya penguraian yang diperlukan untuk memisahkan tabel-tabel itu sangat besar.
Namun, saat Anda beralih ke layanan mikro, Anda harus menyadari bahwa ada lebih sedikit masalah yang disebabkan oleh berbagi perangkat keras dan lisensi di tingkat server. Faktanya, ketika melakukan refactoring awal ke layanan mikro, ada banyak keuntungan untuk menyimpan skema baru yang lebih terpisah dengan lebih bersih di server perusahaan yang sama karena perusahaan biasanya sudah memiliki prosedur untuk backup dan restore basis data dan untuk pembaruan server basis data, yang tim dapat manfaatkan.
Dalam arti tertentu, apa yang ditawarkan perusahaan melalui penyediaan perangkat keras dan perangkat lunak dan manajemen basis data perusahaan adalah versi terbatas dari Database-as-a-Service (DBaaS). Ini terutama cocok dengan pendekatan yang dimulai dengan memisahkan bagian-bagian monolit Anda dengan lebih bersih berdasarkan area fungsional, dimulai dengan pendekatan “Monolit Modular”, seperti yang ditunjukkan pada Gambar 2.
Dalam contoh ini (dimaksudkan untuk menunjukkan pekerjaan refactoring dalam proses), Anda dapat melihat bagaimana basis data telah dipecah dengan memisahkan tabel yang sesuai dengan tiga skema baru (A, B, dan C) yang sesuai dengan modul tertentu dalam aplikasi yang difaktorkan ulang. Setelah mereka dipisahkan seperti ini, mereka dapat dengan bersih dipecah menjadi layanan mikro yang berbeda. Namun, D dan E masih difaktorkan ulang—mereka masih berbagi skema tunggal dengan tabel yang saling berhubungan.
Akhirnya, bahkan penautan di tingkat basis data-server dapat menjadi masalah. Misalnya, Anda terbatas pada fitur yang tersedia dari basis data perusahaan jika itu yang Anda pilih. Bahkan dalam model relasional, tidak semua skema memerlukan semua fitur tersebut, atau mereka mungkin memerlukan fitur yang didukung lebih baik melalui server yang berbeda (misalnya, sharding yang lebih baik sering diangkat sebagai alasan untuk menggunakan basis data NewSQL). Demikian juga, memutakhirkan server basis data yang dibagikan oleh beberapa layanan mikro dapat menurunkan beberapa layanan sekaligus.
Tetapi masalahnya adalah bahwa ini adalah keputusan yang dapat ditunda—tidak harus dibuat segera pada awal proyek. Ketika tim mulai melakukan refactoring, mempertahankan mereka pada server basis data yang sama setidaknya pada tahap awal proyek refactoring adalah cara untuk melakukan perubahan secara bertahap sambil tim memperoleh pengalaman yang diperlukan dalam refactoring kode dan basis data.
Seperti yang telah dibahas sebelumnya, semakin jauh Anda masuk ke proses refactoring, semakin penting untuk mempertimbangkan dengan saksama opsi basis data Anda—karena tidak semua data ideal untuk model relasional. Memutuskan apa pendekatan terbaik untuk mengelola kumpulan data tersebut sering kali bermuara pada pertanyaan “apa yang sebenarnya Anda simpan di basis data Anda?”
Kami telah menghabiskan waktu bertahun-tahun membantu perusahaan membangun, memelihara, dan sering menyiksa kerangka kerja pemetaan relasional objek, tetapi kenyataannya adalah bahwa dalam beberapa kasus, data yang disimpan tidak memetakan dengan baik sama sekali ke model data relasional. Kapan pun itu terjadi, kami mendapati diri kami harus “memutar” model relasional agar sesuai, atau lebih mungkin, melompati rintangan dalam program untuk memaksa kode agar sesuai dengan penyimpanan data relasional.
Sekarang kita telah pindah ke era pilihan ketekunan poliglot, kita dapat memeriksa kembali beberapa keputusan ini dan membuat beberapa yang lebih baik. Secara khusus, kami ingin melihat empat kasus berbeda di mana jelas bahwa model relasional bukanlah pilihan terbaik dan kemudian mempertimbangkan kasus di mana model relasional adalah pilihan terbaik dan menempatkan data dalam bentuk lain tidak akan menjadi pendekatan yang tepat.
Berkali-kali, kami telah melihat melalui kode persistensi sistem perusahaan hanya untuk menemukan, yang mengejutkan kami, bahwa apa yang sebenarnya mereka simpan dalam basis data relasional mereka adalah representasi biner dari objek Java serial. Ini disimpan dalam kolom “Binary Large Object” atau “Blob” dan biasanya merupakan Hasil dari tim yang mengangkat tangan mereka pada kerumitan mencoba memetakan objek Java mereka ke dalam tabel dan kolom relasional. Penyimpanan blob memiliki kelemahan tertentu: Tidak pernah dapat ditanyakan berdasarkan kolom; seringkali lambat; dan sensitif terhadap perubahan struktur objek Java sendiri—data yang lebih lama mungkin tidak dapat dibaca jika struktur objek berubah secara signifikan.
Jika aplikasi Anda (atau, lebih mungkin, subset aplikasi Anda) menggunakan penyimpanan Blob dalam basis data relasional, itu sudah merupakan pertanda yang cukup baik bahwa Anda mungkin lebih baik menggunakan penyimpanan nilai kunci seperti Memcached atau Redis. Di sisi lain, Anda mungkin ingin mundur selangkah dan memikirkan sedikit tentang apa yang Anda simpan. Jika ternyata itu hanya sebuah objek Java terstruktur (mungkin sangat terstruktur, tetapi bukan biner asli) maka Anda mungkin lebih baik menggunakan toko Dokumen seperti Cloudant atau MongoDB. Terlebih lagi, dengan sedikit usaha yang dihabiskan untuk bagaimana Anda menyimpan dokumen Anda (misalnya, kedua basis data yang disebutkan di atas adalah toko dokumen JSON, dan Parser JSON keduanya tersedia secara luas dan mudah disesuaikan) Anda dapat menangani masalah “penyimpangan skema” jauh lebih mudah daripada yang Anda bisa dengan pendekatan penyimpanan Blob, yang jauh lebih buram dalam mekanisme penyimpanannya.
Bertahun-tahun yang lalu, ketika Martin Fowler menulis “Pola Arsitektur Aplikasi Enterprise,” kami memiliki korespondensi aktif dan beberapa pertemuan ulasan yang meriah tentang banyak pola. Salah satunya selalu menonjol sebagai bebek ganjil — pola Rekaman Aktif. Itu aneh karena berasal dari komunitas Java, kami belum pernah menemukannya (meskipun Martin meyakinkan kami bahwa itu umum di komunitas pemrograman Microsoft.NET). Tetapi apa yang benar-benar mengejutkan kami tentang hal itu—dan terutama ketika kami mulai melihat beberapa implementasi Java menggunakan teknologi sumber terbuka seperti iBatis—adalah bahwa tampaknya kasus terbaik untuk menggunakannya adalah ketika objeknya, yah, datar.
Jika objek yang Anda petakan ke basis datasepenuhnya dan benar-benar datar—tanpa hubungan dengan objek lain (dengan pengecualian terbatas mungkin objek bersarang)—maka Anda mungkin tidak memanfaatkan kemampuan penuh model relasional. Bahkan, Anda jauh lebih mungkin untuk menyimpan dokumen. Sangat sering dalam kasus di mana kami telah melihat ini, tim secara harfiah menyimpan versi elektronik dokumen kertas, baik itu survei kepuasan pelanggan, tiket masalah, dll. Dalam situasi itu, basis data dokumen seperti Cloudant atau MongoDB mungkin paling cocok untuk Anda. Membagi kode Anda menjadi layanannya sendiri yang bekerja pada jenis basis data itu akan menghasilkan kode yang jauh lebih sederhana dan seringkali akan lebih mudah dipelihara daripada mencoba melakukan hal yang sama sebagai bagian dari basis data perusahaan besar.
Pola umum lain yang telah kita lihat dalam sistem ORM adalah kombinasi “data referensi dalam tabel tersedot ke dalam cache dalam memori.” Data referensi terdiri atas hal-hal yang tidak sering (atau pernah) diperbarui, tetapi yang terus dibaca. Contoh yang baik dari ini adalah daftar negara bagian A.S atau provinsi Kanada; contoh lain termasuk kode medis atau daftar suku cadang standar. Jenis data ini sering digunakan untuk mengisi drop-down di GUI.
Pola yang umum adalah memulai dengan membaca daftar dari sebuah tabel (biasanya tabel datar dua kolom atau, paling banyak, tiga kolom) setiap kali digunakan. Namun, Anda kemudian akan menemukan bahwa kinerja melakukan itu setiap saat adalah penghalang, jadi sebagai gantinya, aplikasi membacanya ke dalam cache dalam memori seperti EHCache saat startup.
Setiap kali Anda memiliki masalah ini, itu memohon untuk difaktorkan kembali menjadi mekanisme caching yang lebih sederhana dan lebih cepat. Sekali lagi, ini adalah situasi di mana Memcached atau Redis akan sangat masuk akal. Jika data referensi independen dari sisa struktur basis data Anda (dan sering atau, paling banyak, digabungkan secara longgar) maka memisahkan data dan layanannya dari sisa sistem Anda dapat membantu.
Dalam satu sistem pelanggan yang kami kerjakan, kami melakukan pemodelan keuangan kompleks yang membutuhkan kueri yang sangat rumit (pada urutan gabungan enam atau tujuh arah) hanya untuk membuat objek yang dimanipulasi program. Pembaruan bahkan lebih rumit, karena kami harus menggabungkan beberapa tingkat pemeriksaan penguncian optimis yang berbeda hanya untuk mengetahui apa yang telah berubah dan apakah apa yang ada di basis data masih cocok dengan struktur yang telah kami buat dan manipulasi.
Dalam retrospeksi, jelas bahwa apa yang kami lakukan akan lebih alami dimodelkan sebagai grafik. Dalam situasi seperti ini (misalnya ketika kami memodelkan tranche dana yang terdiri dari berbagai jenis ekuitas dan kewajiban utang, masing-masing dinilai dalam mata uang berbeda, memiliki jatuh tempo berbeda, dan mengikuti aturan valuasi yang berbeda), struktur data yang Anda butuhkan hampir jelas—sesuatu yang memungkinkan Anda menelusuri graf naik turun dan memindahkan bagiannya dengan mudah.
Di sinilah solusi seperti Apache Tinkerpop atau Neo4J akan menjadi pendekatan yang baik. Dengan memodelkan solusi secara langsung sebagai grafik, kami dapat menghindari banyak kode Java dan SQL yang rumit, dan pada saat yang sama, mungkin secara signifikan meningkatkan kinerja waktu proses kami.
Meskipun ada banyak kasus di mana basis data NoSQL adalah pendekatan logis yang tepat untuk struktur data tertentu, seringkali sulit untuk mengalahkan fleksibilitas dan kekuatan model relasional. Hal hebat tentang basis data relasional adalah Anda dapat dengan sangat efektif “mengiris dan memotong” data yang sama ke dalam bentuk yang berbeda untuk tujuan yang berbeda. Trik seperti Database Views memungkinkan Anda membuat beberapa pemetaan dari data yang sama—sesuatu yang sering berguna saat mengimplementasikan serangkaian kueri terkait dari model data yang kompleks.
Untuk menyelam lebih dalam tentang perbandingan NoSQL dan SQL lihat “SQL vs NoSQL: Apa Perbedaannya?”
Seperti yang kita bahas di artikel sebelumnya, jika “batas bawah” dari layanan mikro adalah sekumpulan Entitas yang dikelompokkan ke dalam Agregat bersama dengan kumpulan Layanan terkait yang beroperasi pada data itu, menerapkan tampilan untuk mewakili serangkaian kueri terkait seringkali paling mudah dan paling mudah dengan SQL.
Kami pertama kali melihatnya dalam contoh pelanggan yang mengarah ke contoh akun/LineItem sederhana kami di artikel sebelumnya. Dalam hal ini, ada bank yang berusaha sangat keras untuk membuat model sederhana seperti itu bekerja dalam basis data NoSQL berorientasi dokumen, hanya untuk dikalahkan oleh teorema CAP. Namun, tim telah memilih model data itu untuk semua alasan yang salah. Mereka telah memilih untuk menggunakan basis data berorientasi dokumen untuk semua layanan mikro mereka yang beragam karena keinginan yang salah untuk konsistensi arsitektur.
Dalam hal ini, mereka membutuhkan semua atribut mode ACID, tetapi mereka tidak memerlukan sharding (misalnya, partisi); sistem mereka yang ada telah berfungsi selama bertahun-tahun pada tingkat kinerja yang sepenuhnya dapat diterima pada model relasional, dan mereka tidak mengantisipasi pertumbuhan yang sangat besar. Tetapi, meskipun inti dari sistem membutuhkan transaksi ACID dan tidak perlu partisi, itu tidak selalu benar untuk semua bagian yang berbeda dari sistem mereka. Ada beberapa hal yang hebat dalam basis data SQL, dan transaksi ACID adalah salah satunya. Dalam sistem layanan mikro, mengelompokkan transaksi ACID bersama-sama di sekitar kumpulan data terkecil yang mereka operasikan biasanya merupakan pendekatan yang tepat.
Namun, SQL tidak selalu berarti SQL Database tradisional. Itu bisa, dan tentu saja ada tempat untuk itu di banyak arsitektur layanan mikro, tetapi SQL juga diimplementasikan dalam setidaknya dua jenis basis data lain yang dapat menjadi pilihan yang berguna bagi banyak tim yang menerapkan layanan mikro. Yang pertama adalah “SQL kecil,” yang merupakan domain basis data sumber terbuka seperti MySQL dan Postgres. Bagi banyak tim yang menerapkan layanan mikro, basis data ini adalah pilihan yang sangat masuk akal karena berbagai alasan:
Kelemahan utama menggunakan basis data "SQL kecil" ini adalah bahwa mereka sering tidak mendukung tingkat skala yang sama (terutama yang berkaitan dengan sharding) yang dapat didukung oleh basis data SQL perusahaan. Namun, ini telah ditangani dengan mengagumkan oleh seperangkat vendor basis data baru dan proyek sumber terbuka yang menggabungkan atribut terbaik dari basis data SQL dan skalabilitas basis data NoSQL. Sering disebut basis data “NewSQL”, ini termasuk CockroachDB, Apache Trofidion, dan Clustrix.
Kapan pun Anda membutuhkan semua transaksi ACID, mesin SQL yang sepenuhnya mendukung model relasional, dan juga kemampuan penskalaan dan sharding yang luas, basis data NewSQL dapat menjadi pilihan yang baik untuk tim. Pilihan itu datang dengan biaya–basis data ini seringkali lebih kompleks untuk diatur dan dikelola daripada solusi “SQL kecil” yang lebih lama. Juga lebih sulit untuk menemukan orang dengan keterampilan dalam basis data ini. Bagaimanapun, mereka masih perlu dipertimbangkan dengan cermat saat mengerjakan opsi Anda.
Kami telah melakukan perjalanan singkat melalui sejumlah masalah pemodelan basis data yang berbeda yang dapat menyamar sebagai masalah pengodean. Jika Anda menemukan Anda memiliki satu atau lebih masalah khusus ini, maka Anda mungkin lebih baik memisahkan diri dari penyimpanan data perusahaan Anda yang ada dan membayangkannya kembali dengan jenis penyimpanan data yang berbeda. Saran kami adalah, bagaimanapun, lakukan ini secara perlahan dan bertahap. Ketahuilah bahwa tidak semua aplikasi memerlukan semua jenis model data dan bahwa Anda perlu membangun keterampilan dan mendapatkan pemahaman tentang kemampuan operasional basis data pilihan Anda dari waktu ke waktu sebelum Anda mulai mengimplementasikannya dalam skala yang luas.
Akhirnya, sadari fakta bahwa seluruh pendekatan layanan mikro didasarkan pada gagasan bahwa tim yang membangun setiap layanan mikro dapat membuat keputusan sendiri tentang penyimpanan data apa yang tepat untuk mereka. Satu masalah terbesar yang kami temui (seperti yang diisyaratkan banyak dari cerita ini) adalah mencoba membuat representasi satu data dan pendekatan penyimpanan berfungsi untuk semua situasi.
Sering kali saya melihat tim harus mencoba dan menangani realitas teorema CAP dalam situasi di mana mereka seharusnya tidak menggunakan basis data NoSQL. Demikian juga, mencoba melakukan pelaporan kompleks dari basis data NoSQL seringkali merupakan latihan frustrasi. Di sisi lain, situasi yang kami tunjukkan menunjukkan bahwa model relasional tidak mencakup semuanya. Model lain juga punya tempatnya. Satu saran terbaik yang dapat kami berikan adalah memastikan bahwa tim Anda memiliki otonomi yang diperlukan untuk memilih model yang tepat untuk setiap layanan mikro.
IBM® Garage dibuat untuk bergerak lebih cepat, bekerja lebih cerdas, dan berinovasi dengan cara yang memungkinkan Anda mengganggu gangguan.
Memanfaatkan kekuatan AI dan otomatisasi untuk memecahkan masalah secara proaktif di seluruh tumpukan aplikasi.
Gunakan perangkat lunak dan alat bantu DevOps untuk membangun, menerapkan, dan mengelola aplikasi cloud native di berbagai perangkat dan lingkungan.
Percepat ketangkasan dan pertumbuhan bisnis — terus modernisasi aplikasi Anda di platform apa pun menggunakan layanan konsultasi cloud kami.