Layanan yang diberikan (CMS) yang mengontrol model (Produk, mari kita asumsikan satu-satunya bidang yang dimilikinya adalah id, judul, harga) dan layanan B (Pengiriman) dan C (Email) yang harus menampilkan model yang diberikan apa yang harus pendekatan untuk menyinkronkan informasi model yang diberikan di seluruh layanan tersebut dalam pendekatan sumber acara? Mari kita asumsikan bahwa katalog produk jarang berubah (tetapi tidak berubah) dan bahwa ada admin yang dapat mengakses data pengiriman dan email sangat sering (contoh fungsi adalah: B: display titles of products the order contained
dan C:) display content of email about shipping that is going to be sent
. Setiap layanan memiliki DB sendiri.
Solusi 1
Kirim semua informasi yang diperlukan tentang Produk dalam acara - ini berarti struktur berikut untuk order_placed
:
{
order_id: [guid],
product: {
id: [guid],
title: 'Foo',
price: 1000
}
}
Pada layanan B dan C informasi produk disimpan dalam product
atribut JSON di atas orders
meja
Dengan demikian, untuk menampilkan informasi yang diperlukan hanya data yang diambil dari acara yang digunakan
Masalah : tergantung pada informasi apa yang perlu disajikan dalam B dan C, jumlah data dalam acara dapat bertambah. B dan C mungkin tidak memerlukan informasi yang sama tentang Produk, tetapi acara harus mengandung keduanya (kecuali jika kami memisahkan acara menjadi dua). Jika data yang diberikan tidak ada dalam acara yang diberikan, kode tidak dapat menggunakannya - jika kami akan menambahkan opsi warna ke Produk yang diberikan, untuk pesanan yang ada dalam B dan C, produk yang diberikan tidak akan berwarna kecuali jika kami memperbarui acara dan kemudian memutarnya kembali. .
Solusi 2
Kirim hanya panduan produk dalam acara - ini berarti struktur berikut untuk order_placed
:
{
order_id: [guid],
product_id: [guid]
}
Pada layanan, informasi produk B dan C disimpan dalam product_id
atribut di atas orders
meja
Informasi produk diambil oleh layanan B dan C bila diperlukan dengan melakukan panggilan API ke A/product/[guid]
titik akhir
Masalah : ini membuat B dan C tergantung pada A (setiap saat). Jika skema perubahan Produk pada A, perubahan harus dilakukan pada semua layanan yang bergantung padanya (tiba-tiba)
Solusi 3
Kirim hanya panduan produk dalam acara - ini berarti struktur berikut untuk order_placed:
{
order_id: [guid],
product_id: [guid]
}
Pada layanan informasi produk B dan C disimpan dalam products
tabel; masih ada di product_id
atas orders
meja, tetapi ada replikasi products
data antara A, B dan C; B dan C mungkin mengandung informasi berbeda tentang Produk daripada A
Informasi produk diunggulkan ketika layanan B dan C dibuat dan diperbarui setiap kali informasi tentang Produk berubah dengan melakukan panggilan ke A/product
endpoint (yang menampilkan informasi yang diperlukan dari semua produk) atau dengan melakukan akses DB langsung ke A dan menyalin informasi produk yang diperlukan yang diperlukan untuk diberikan layanan.
Masalah : ini membuat B dan C tergantung pada A (saat penyemaian). Jika skema perubahan Produk pada A, perubahan harus dilakukan pada semua layanan yang bergantung padanya (saat penyemaian)
Dari pemahaman saya, pendekatan yang benar adalah dengan solusi 1, dan memperbarui riwayat peristiwa per logika tertentu (jika katalog Produk tidak berubah dan kami ingin menambahkan warna untuk ditampilkan, kami dapat dengan aman memperbarui riwayat untuk mendapatkan keadaan saat ini) Produk dan mengisi data yang hilang dalam acara tersebut) atau melayani tidak adanya data yang diberikan (jika katalog Produk telah berubah dan kami ingin menambahkan warna untuk ditampilkan, kami tidak dapat memastikan apakah pada titik waktu di masa lalu Produk yang diberikan memiliki warna atau tidak - kita dapat mengasumsikan bahwa semua Produk dalam katalog sebelumnya berwarna hitam dan diperuntukkan dengan memperbarui acara atau kode)
sumber
updating event history
- Dalam peristiwa sumber sejarah acara adalah sumber kebenaran Anda dan tidak boleh diubah tetapi hanya maju. Jika acara berubah, Anda dapat menggunakan versi acara atau solusi serupa tetapi saat memutar ulang acara hingga titik waktu tertentu, keadaan data harus seperti saat itu.updating event history
maksud saya: pergi melalui semua peristiwa, menyalinnya dari satu aliran (v1) ke aliran lain (v2) untuk mempertahankan skema acara yang konsisten.display image at the point when purchase was made
) atau tidak bisa (mewakili maksuddisplay current image as it within catalog
)Jawaban:
Solusi # 3 sangat dekat dengan ide yang tepat.
Cara untuk berpikir tentang ini: B dan C masing-masing menyimpan salinan "lokal" dari data yang mereka butuhkan. Pesan yang diproses di B (dan juga di C) menggunakan informasi yang di-cache secara lokal. Demikian juga, laporan dihasilkan menggunakan informasi yang di-cache secara lokal.
Data direplikasi dari sumber ke cache melalui API yang stabil. B dan C bahkan tidak perlu menggunakan API yang sama - mereka menggunakan protokol pengambilan apa pun yang sesuai dengan kebutuhan mereka. Akibatnya, kami mendefinisikan kontrak - protokol dan skema pesan - yang membatasi penyedia dan konsumen. Kemudian setiap konsumen untuk kontrak itu dapat terhubung ke pemasok mana pun. Perubahan mundur yang tidak kompatibel memerlukan kontrak baru.
Layanan memilih strategi pembatalan cache yang sesuai untuk kebutuhan mereka. Ini mungkin berarti menarik perubahan dari sumber pada jadwal reguler, atau sebagai tanggapan terhadap pemberitahuan bahwa hal-hal mungkin telah berubah, atau bahkan "sesuai permintaan" - bertindak sebagai cache yang dibaca, kembali ke salinan data yang tersimpan saat sumbernya tidak tersedia.
Ini memberi Anda "otonomi", dalam arti bahwa B dan C dapat terus memberikan nilai bisnis ketika A sementara tidak tersedia.
Bacaan yang disarankan: Data di Luar, Data di Dalam , Pat Helland 2005.
sumber
Ada dua hal yang sulit dalam Ilmu Komputer, dan salah satunya adalah pembatalan cache.
Solusi 2 benar-benar posisi default saya, dan Anda seharusnya hanya mempertimbangkan untuk mengimplementasikan caching jika Anda mengalami salah satu dari skenario berikut:
Masalah kinerja adalah pendorong utama. Ada banyak cara untuk menyelesaikan # 2 yang tidak melibatkan caching, seperti memastikan Layanan A sangat tersedia.
Caching menambah kompleksitas yang signifikan pada sistem, dan dapat membuat kasus tepi yang sulit dipikirkan, dan bug yang sangat sulit untuk ditiru. Anda juga harus mengurangi risiko menyediakan data basi ketika ada data yang lebih baru, yang bisa jauh lebih buruk dari perspektif bisnis daripada (misalnya) menampilkan pesan bahwa "Layanan A sedang down - silakan coba lagi nanti."
Dari artikel yang luar biasa ini oleh Udi Dahan:
Selain itu, Jika Anda memerlukan kueri data waktu produk secara berkala, ini harus ditangani dengan cara data disimpan dalam basis data Produk (mis. Tanggal mulai / berakhir), harus dengan jelas diekspos dalam API (tanggal efektif perlu menjadi input untuk panggilan API untuk meminta data).
sumber
Sangat sulit untuk mengatakan bahwa satu solusi lebih baik daripada solusi lainnya. Memilih satu di antara Solusi # 2 dan # 3 tergantung pada faktor-faktor lain (durasi cache, toleransi konsistensi, ...)
2 sen saya:
Pembatalan cache mungkin sulit tetapi pernyataan masalah menyebutkan bahwa katalog produk jarang berubah. Fakta ini membuat data produk kandidat yang baik untuk caching
Solusi # 1 (NOK)
Solusi # 2 (OK)
Solusi # 3 (Kompleks tetapi disukai)
sumber
Secara umum, saya akan sangat menyarankan terhadap opsi 2 karena kopling sementara antara kedua layanan (kecuali komunikasi antara layanan ini sangat stabil, dan tidak terlalu sering). Penggabungan sementara adalah apa yang Anda gambarkan sebagai
this makes B and C dependant upon A (at all times)
, dan berarti bahwa jika A turun atau tidak dapat dijangkau dari B atau C, B dan C tidak dapat memenuhi fungsinya.Saya pribadi percaya bahwa kedua opsi 1 dan 3 memiliki situasi di mana mereka adalah opsi yang valid.
Jika komunikasi antara A dan B & C sangat tinggi, atau jumlah data yang diperlukan untuk menghadiri acara cukup besar untuk menjadikannya perhatian, maka opsi 3 adalah pilihan terbaik, karena beban pada jaringan jauh lebih rendah , dan latensi operasi akan berkurang ketika ukuran pesan berkurang. Kekhawatiran lain yang perlu dipertimbangkan di sini adalah:
Opsi 1 bukanlah sesuatu yang saya tolak. Ada jumlah yang sama dari kopling, tetapi pengembangan-bijaksana itu harus mudah dilakukan (tidak perlu untuk tindakan khusus), dan stabilitas domain harus berarti bahwa ini tidak akan sering berubah (seperti yang saya sebutkan sebelumnya).
Pilihan lain yang saya sarankan adalah sedikit variasi ke 3, yang bukan untuk menjalankan proses selama start-up, tetapi mengamati acara "ProductAdded dan" ProductDetailsChanged "pada B dan C, ketika ada perubahan dalam katalog produk di A. Ini akan membuat penyebaran Anda lebih cepat (dan jadi lebih mudah untuk memperbaiki masalah / bug jika Anda menemukannya).
Edit 2020-03-03
Saya memiliki urutan prioritas tertentu ketika menentukan pendekatan integrasi:
Jika biaya inkonsistensi tinggi, (pada dasarnya data produk dalam A harus konsisten sesegera mungkin dengan produk yang di-cache dalam B dan C), maka Anda tidak dapat menghindari keharusan menerima ketidakberuntungan, dan membuat permintaan sinkron (seperti web / rest request) dari B & C ke A untuk mengambil data. Waspadalah! Ini masih tidak berarti konsisten secara transaksi, tetapi hanya meminimalkan jendela untuk inkonsistensi. Jika Anda benar-benar, secara positif harus segera konsisten, Anda perlu mengubah batas layanan Anda. Namun, saya sangat yakin ini seharusnya tidak menjadi masalah. Dari pengalaman, sebenarnya sangat jarang bahwa perusahaan tidak dapat menerima beberapa detik inkonsistensi, jadi Anda bahkan tidak perlu membuat permintaan sinkron.
Jika Anda memang membutuhkan pertanyaan point-in-time (yang tidak saya perhatikan dalam pertanyaan Anda dan karenanya tidak termasuk di atas, mungkin salah), biaya mempertahankan ini pada layanan hilir sangat tinggi (Anda harus menduplikasi logika proyeksi peristiwa internal di semua layanan hilir) yang membuat keputusan menjadi jelas: Anda harus meninggalkan kepemilikan ke A, dan meminta A ad-hoc atas permintaan web (atau yang serupa), dan A harus menggunakan sumber acara untuk mengambil semua peristiwa yang Anda ketahui tentang pada saat memproyeksikan ke negara, dan mengembalikannya. Saya kira ini mungkin opsi 2 (jika saya mengerti dengan benar?), Tetapi biayanya sedemikian sehingga sementara kopling temporal lebih baik daripada biaya pemeliharaan peristiwa duplciated dan logika proyeksi.
Jika Anda tidak memerlukan titik waktu, dan tidak ada pemilik data yang jelas (yang dalam jawaban awal saya, saya berasumsi ini berdasarkan pertanyaan Anda), maka pola yang sangat masuk akal adalah mengadakan representasi dari produk di setiap layanan secara terpisah. Ketika Anda memperbarui data untuk produk, Anda memperbarui A, B dan C secara paralel dengan membuat permintaan web paralel untuk masing-masing, atau Anda memiliki API perintah yang mengirim beberapa perintah ke masing-masing A, B dan C. B & C menggunakan mereka versi lokal dari data untuk melakukan pekerjaan mereka, yang mungkin basi atau tidak. Ini bukan salah satu dari opsi di atas (walaupun bisa dibuat dekat dengan opsi 3), karena data dalam A, B dan C mungkin berbeda, dan "keseluruhan" produk mungkin merupakan komposisi dari ketiga data sumber.
Mengetahui apakah sumber kebenaran memiliki kontrak stabil berguna karena Anda dapat menggunakannya untuk menggunakan domain / acara internal (atau acara yang Anda simpan di sumber acara Anda sebagai pola penyimpanan di A) untuk integrasi di seluruh A dan layanan B dan C. Jika kontrak stabil Anda dapat mengintegrasikan melalui peristiwa domain. Namun, maka Anda memiliki kekhawatiran tambahan dalam kasus di mana perubahan sering terjadi, atau bahwa kontrak pesan cukup besar yang membuat transportasi menjadi masalah.
Jika Anda memiliki pemilik yang jelas, dengan kontras yang diharapkan stabil, opsi terbaik adalah opsi 1; pesanan akan berisi semua informasi yang diperlukan dan kemudian B dan C akan melakukan fungsinya menggunakan data dalam acara tersebut.
Jika kontrak cenderung berubah, atau sering rusak, mengikuti opsi 3 Anda, itu kembali ke permintaan web untuk mengambil data produk sebenarnya merupakan pilihan yang lebih baik, karena itu jauh lebih mudah untuk mempertahankan beberapa versi. Jadi B akan membuat permintaan pada v3 produk.
sumber
ProductAdded
atauProductDetailsChanged
menambah kerumitan pelacakan perubahan katalog produk kami perlu menjaga agar data disinkronkan antara database dalam beberapa cara, dalam kasus peristiwa diputar ulang dan kami perlu mengakses data katalog dari masa lalu.