Mendesain Event-Driven Architecture — Part 7

Stateful Pattern pada Microservices

D. Husni Fahri Rizal
The Legend
7 min readNov 30, 2021

--

Pada penjelasan di artikel dengan judul Mendesain Event-Driven Architecture — Part 4 telah dijelaskan dan diperkenalkan event sebagai kolaborasi pada suatu sistem. Pada sistem yang berjalan berdasarkan event driven beberapa service akan bekerjasama mengirimkan atau mendorong semua proses sebagai aliran dari event atau kejadian.

Dari semua itu akan mengarah pada terbentuknya log dari semua proses dan data perubahan status yang dibuat oleh sistem akan disimpan secara permanen. Pada akhirnya terbentuknya log ini akan mengarah pada dua pattern yang sering digunakan dan cukup terkenal yaitu Command Query Response Segregation (CQRS) dan Event Sourcing.

Event Sourcing, Command Sourcing, dan CQRS

Secara garis besar, event sourcing hanyalah sebuah kegiatan memonitor event contohnya perubahan state atau status yang merupakan core dari semua sistem. Apabila event ini disimpan secara permanen, diurutkan berdasarkan waktu terbentuknya, log informasi ini akan memberikan informasi yang cukup lengkap mengenai apa yang terjadi dan dilakukan oleh sistem.

Kelebihan lainnya adalah kita akan selalu dapat menjalankan ulang state sistem yang telah terjadi dengan cara mengulang log dan mengirim ulang event.

CQRS sendiri adalah pengembangan secara alami dari event sourcing pattern. Sebagai contoh sederhana kita dapat mengirimkan event ke kafka di baca kembali (listener) dan di bagian konsumernya kita tulis data dari event pada database lainnya ( secondary database ) untuk digunakan pada proses pembacaan data dengan tingkat frekuensi pembacaan data yang sangat sering.

Singkatnya dengan CQRS kita dapat memisahkan antar proses penulisan ke data dan proses read data pada dua sistem database yang berbeda. Tentunya pemilihan database untuk read akan berbeda dengan pemilihan database untuk proses write.

CS atau command sourcing pada dasarnya adalah varian dari event sourcing tetapi diterapkan pada event yang datang pada service bukan pada setiap event yang terjadi.

Berikut adalah penjelasan dengan diagram agar kita memiliki pemahaman yang lebih bagus. Misalkan, pada proses pembelian pada sistem e-commerce.

Pada saat order pembelian terjadi (1), request yang masuk ke akan ditulis dalam log sebagai sebuah event sebelum event ini di publish ke Kafka (2). Dengan demikian, jika terjadi suatu masalah maka event ini dapat kita jalankan ulang.

Selanjutnya masuk ke proses validasi order dan apabila tervalidasi, event akan disimpan juga dalam log sebagai event oder validate (3). Pada proses 3 ini sebenarnya hanya merubah status dari event tetapi tetap membuat sebuah record baru. Berbeda dengan proses update in place atau proses CRUD yang mengupdate data lama. Jantung dari event sorcing adalah penulisan baru semua event dan tidak ada proses update di database untuk suatu data.

Akhirnya setelah proses beres maka dibuat event untuk mengirimkan event order ini ke bagian query service untuk menampilkan hasil order (4). Dengan demikian proses 1 adalah sisi command dan proses 4 adalah sisi query dari proses CQRS.

Versioning Data Kita

Misalkan kita punya sebuah service Order dengan penambahan kemampuan membuat bug secara programatik. Adapun, kesalahan yang terjadi misalkan penanganan waktu timestamp karena zona waktu yang salah.

Kesalahan atau bug tersebut akan tersimpan ke dalam database dan permasalahan ini tersebar pula ke service-service lainnya karena terdapat interaksi antar service. Dengan demikian, proses fixing akan menjadi sangat berat karena problematika sudah tersebar secara luas.

Programmatic Bug

Proses fixing kondisi di atas akan sangat sulit karena beberapa alasan berikut.

  1. Permasalahan mendasar adalah kita belum mempunyai penyimpanan data dengan tepat. Kita hanya memiliki record order yang problem dan kita harus membongkar secara manual untuk proses perbaikannya.
  2. Tidak seperti versi kontrol yang dapat menjalankan kembali semua proses dari awal, sistem di atas hanya berisi database yang berubah di tempat saja. Dalam hal ini kita hanya memiliki versi data terakhir dan versi sebelum nya sudah hilang.

Adapun untuk melakukan perbaikan hal seperti ini biasanya dilakukan sebagai berikut.

  1. Perbaiki kode yang mengakibatkan bug terjadi.
  2. Menjalankan script ke database untuk fixing data dengan timestamp yang benar.
  3. Mencari cara untuk mengirim ulang data yang sudah diperbaiki tadi ke service lainya.
  4. Kadang butuh rollback ke versi sebelumnya dan migrasi data semakin kompleks.

Apabila kita merubah sistem di atas dengan pendekatan event dan command sourcing maka input dan output setiap state atau kondisi nya akan di record dan disimpan. Adapun diagram proses yang terjadi sebagai berikut.

Dengan sistem kedua ini kita akan memiliki data yang benar dan tersimpan di database sebelum bug tereksekusi. Dengan demikian, kita memiliki dua data yakni data yang benar dan data yang sudah terkontaminasi bug.

Seperti dijelaskan di pembahasan Mendesain Event-Driven Architecture — Part 2 bahwa Kafka dapat menyimpan event dalam jangka waktu yang lama maka proses perbaikan bug yang terjadi menjadi lebih mudah.

Kita perbaiki bug pada software dan setelahnya kita tinggal mengirim ulang data yang benar dari CS ini ke sistem. Secara natural data yang bermasalah akan di overwrite dengan data yang benar serta data yang benar ini akan tersebar secara otomatis ke service-service lainnya.

Jadi CS memungkinkan kita dapat menyimpan semua input dan sistem dapat di putar ulang. Event sourcing akan merekam semua proses dan perubahannya statusnya serta kita akan mengetahui apa yang terjadi pada sistem kita dengan jelas.

CS memungkinkan kita mengeksekusi proses dari awal (order asli ) dan event sourcing memungkinkan kita mengetahui semua proses dari awal sampai akhir

Mempunyai kemampuan menyimpan semua status dari sistem memberikan kemampuan kepada kita melakukan debugging dan tracking lebih mudah. Sehingga pertanyaan seperti “Mengapa Order ini secara misterius gagal atau di tolak” akan mudah di jawab.

Event Sourcing ensures every state change in a system is recorded, much like a version control system. As the saying goes, “Accountants don’t use erasers.

Event sebagai Sumber Kebenaran

Salah satu efek baik dari penerapan implementasi terakhir di atas adalah event sourcing menjadikan event (bukan database record) sebagai sumber kebenaran (source of truth).Hal ini akan memberikan dampak-dampak positif lainnya bagi sistem kita.

Apabila kita perhatikan implementasi pertama maka jelas terlihat terdapat dua versi dari order. Satu pada database dan satu lagi pada notifikasi ke service-service lainnya. Kondisi ini akan mengarah pada problematika berikut

  1. Notifikasi dan database harus dieksekusi secara atomic.
  2. Apabila terjadi kesalahan ketika proses update database atau kesalahan ketika notifikasi dikirimkan maka akan terjadi duplikasi notifikasi (best case) atau notifikasi tidak dikirim sama sekali (worst case)
Order tervalidasi dan notifikasi dikirim tetapi problem terjadi sebelum penulisan ke database.

Event sourcing dapat menangani dua permasalahan tersebut dengan mudah dan apalagi jika kita terapkan Saga Pattern akan menjadi sangat yakin konsistensi data bisa kita jamin dengan benar.

Event Sourcing ensures that the state a service communicates and the state a service saves internally are the same.

Command Query Responsibility Segregation

Seperti dijelaskan sebelumnya bahwa CQRS adalah membagi proses penulisan data dan pembacaan data secara terpisah dan menghubungkan keduanya secara asinkron.

Idea ini tidak terbatas pada aplikasi design saja tetapi dapat kita terapkan pada berbagai macam bagian atau proses dari software development. Contohnya pada proses internal penyimpanan data di database sebenarnya mengimplementasikan CQRS.

Apabila kita menerapkan CQRS pada software kita maka proses dapat kita jalankan dengan alasan yang mirip dengan penulisan data di internal database.

Input data di jurnal ke Kafka yang lebih cepat daripada penulisan ke database. Pada waktu yang sama secara asinkron proses penulisan data ke database utama dan database kedua untuk proses read dilakukan. Di sisi lain proses baca dan tulis akan memiliki performance yang lebih bagus karena tidak terjadi locking dan update index secara bersamaan.

Tentu saja tidak ada semua yang bersifat gratis. Karena proses baca data di update secara asinkron maka data di bagian read akan ada jeda waktu sebelum tersedia. Biasanya data akan ada setelah data tersimpan di database utama. Untuk hal-hal ini dalam arti optimalisasi jeda waktu akan kita bahas di penjelasan tersendiri.

Untuk mempelajari lebih dalam mengenai CQRS dapat di baca di artikel-artikel berikut.

  1. https://medium.com/the-legend/cqrs-81b2de39dfd5
  2. https://medium.com/the-legend/real-production-success-story-cqrs-pattern-74b35dab486d

Apa Selanjutnya

Kita telah mengetahui beberapa statefull patten utama. Di penjelasan selanjutnya kita akan membahas beberapa tambahan dari stateful pattern. Stay Tuned aja!

References

  1. Adam Bellemare. 2020. Building Event-Driven Microservices. USA: O’Reilly Media, Inc.
  2. Escoffier, Clement. 2017. Building Reactive Microservices in Java. USA: O’Reilly Media, Inc.
  3. Stopford, Ben. 2018. Designing Event-Driven System. USA: O’Reilly Media, Inc.
  4. Boner, Jonas. 2016. Reactive Microservice Architecture. USA: O’Reilly Media, Inc.

Sponsor

Membutuhkan kaos dengan tema pemrograman :

Kafka T-shirt

Elastic T-shirt

Dapat menghubungi The Legend.

--

--

D. Husni Fahri Rizal
The Legend

Engineering Leader | Start-Up Advisor | Agile Coach | Microservices Expert | Professional Trainer | Investor Pemula