Sumber acara, pemutaran ulang, dan versi

8

Saya merancang sistem yang menggunakan Pengadaan Acara, CQRS, dan layanan mikro. Saya mengerti bahwa ini bukan pola yang tidak biasa. Fitur utama dari layanan ini adalah kemampuan untuk merehidrasi / memulihkan dari sistem catatan. Layanan Microsoft akan menghasilkan perintah dan permintaan pada MQ (Kafka). Layanan microser lainnya akan merespons (acara). Perintah dan pertanyaan akan tetap ada pada S3 untuk tujuan audit dan pemulihan.

Proses pemikiran saat ini adalah bahwa, untuk tujuan memulihkan sistem, kita dapat mengekstrak log peristiwa dari S3 dan hanya memasukkannya kembali ke Kafka.

Namun, ini gagal untuk mengakui perubahan produsen dan konsumen dari waktu ke waktu. Versi pada tingkat perintah / kueri tampaknya menuju penyelesaian masalah tetapi saya tidak bisa memahami konsumen versi sehingga saya bisa menegakkan bahwa ketika perintah, selama pemulihan, diterima dan diproses, itu sama persis kode [versi] yang melakukan pemrosesan karena ini adalah pertama kalinya perintah diterima.

Apakah ada pola yang bisa saya gunakan untuk menyelesaikan ini? Adakah yang mengetahui sistem lain yang mengiklankan fitur ini?

EDIT: Menambahkan contoh.

'Pembeli' mengirim 'pertanyaan' ke 'penjual' di situs lelang saya. Alurnya terlihat sebagai berikut: UI -> Web App: POST /question {:text text :to seller-id :from user-id} Web App -> MQ: SEND {:command send-question :args [text seller-id user-id]} MQ -< Audit: <command + args appended to log in S3> MQ -< Questions service: - Record question in DB - Email seller 'You have a question'

Sekarang, sebagai hasil dari persyaratan bisnis baru, saya menyesuaikan konsumen 'Layanan pertanyaan', untuk bertahan dalam hitungan semua pertanyaan yang belum dibaca. Skema DB diubah. Kami belum memiliki gagasan apakah pertanyaan dibacakan oleh penjual, sampai sekarang. Baris terakhir menjadi:

MQ -< Questions service: - Record question in DB - Email seller 'You have a question' - Increment 'unread questions count'

Dua perintah adalah masalah, satu sebelum perubahan, satu setelah perubahan. 'Jumlah pertanyaan yang belum dibaca' sama dengan 1.

Sistem macet. Kami memulihkan dengan memutar ulang perintah melalui kode baru . Pada akhir pemulihan, 'jumlah pertanyaan yang belum dibaca' kami sama dengan 2. Meskipun, dalam contoh yang dibuat-buat ini, hasilnya bukan bencana, keadaan yang telah dipulihkan bukan seperti sebelumnya.

Antony Woods
sumber
Pertanyaan itu tampaknya mencampuradukkan beberapa kekhawatiran. Sumber acara adalah strategi arsitektur untuk berurusan dengan sistem di mana banyak perubahan pada data yang mendasarinya terjadi. Versi DTO dan cadangan dan data adalah masalah lain. Pengadaan acara tidak dirancang khusus untuk membuat Anda memiliki kemampuan pemulihan bare-metal - untuk itu, Anda harus memiliki strategi khusus.
theMayer
Mungkin acara penyiaran dapat menyelesaikan masalah Anda: blog.trifork.com/2012/04/17/…
Songo
@ rmayer06 Saya pikir contoh adalah apa yang saya cari!
Antony Woods

Jawaban:

16

Pertama, penting untuk memahami dan dapat memanfaatkan perbedaan antara Perintah dan Acara.

Seperti yang ditunjukkan oleh pertanyaan ini dengan singkat, Perintah adalah hal-hal yang kita inginkan terjadi, dan Peristiwa adalah hal-hal yang telah terjadi. Perintah tidak selalu menghasilkan peristiwa penting dalam sistem, tetapi biasanya terjadi. Sebagai contoh, sebuah send messageperintah dapat ditolak, dalam hal ini tidak ada peristiwa yang terjadi (biasanya kesalahan tidak akan dianggap sebagai peristiwa dalam pengertian ini, meskipun kami mungkin masih memilih untuk mencatatnya dalam log diagnostik). Sekarang, jika send messageperintah diterima, message sentacara terjadi, dan detail acara dapat menggambarkan pengirim, penerima, dan konten.

Ketika kita berbicara tentang status sistem, kita sebenarnya membahas bukan puncak dari perintah, tetapi tentang peristiwa. Hanya acara yang dapat menyebabkan perubahan status dalam sistem. Untuk menarik dari contoh kehidupan, misalkan saya pergi ke supermarket Publix lokal dan membeli tiket lotere Florida. Perintahnya adalah "Beli Tiket" dan acara itu "Tiket dikeluarkan." Perintah saya selanjutnya adalah lotre untuk menggambar nomor saya untuk PowerBall. Lotre akan mengabaikan perintah saya (tapi saya tidak tahu), dan acara "nomor PowerBall terpilih" terjadi terlepas dari keinginan saya. Jika nomor saya cocok, acara "Jackpot won" terjadi pada saya (dan saya pikir perintah saya didengar). Jika tidak, saya menyadari bahwa perintah saya diabaikan.

Dari perspektif sejarah, lotere hanya tertarik pada sebagian dari peristiwa. Lotre hanya peduli bahwa (a) tiket dikeluarkan, (b) nomor dipilih, dan (c) jackpot dimenangkan. Itu adalah item yang menarik. Tindakan membeli tiket, ingin menang, dll. Semua tidak relevan, seperti apa yang saya lakukan dengan tiket saya setelah saya kalah. Sementara dunia nyata memang berubah untuk peristiwa duniawi, kita hanya perlu mencatat peristiwa-peristiwa yang penting bagi sistem kita.

Secara teori, di bawah teknik event-sourcing, aliran peristiwa dapat diputar ulang dari awal waktu untuk sampai pada keadaan saat ini. Ini bergantung pada asumsi bahwa kondisi sistem yang mendasarinya adalah konstan dan deterministik. Namun, asumsi ini tidak berlaku di banyak sistem. Data yang terkait dengan suatu peristiwa, serta jenis peristiwa yang kami minati, dapat berubah seiring berkembangnya perangkat lunak komputer kami. Selain itu, komputasi dapat menjadi mahal untuk menghitung kembali keadaan saat ini sebagai respons atas setiap permintaan. Untuk alasan ini, snapshot dari keadaan sistem sering diambil untuk mewakili titik waktu yang diketahui, yang kemudian ditambahkan ke sebagian besar peristiwa terkini.

Meskipun masih mungkin untuk memutar ulang arus peristiwa di berbagai versi, jumlah upaya manusia yang terlibat dalam melakukan hal itu kemungkinan akan menjadi penghalang biaya. Kecuali jika ada alasan yang dapat dibenarkan untuk merancang kemampuan itu ke dalam sistem, Anda lebih baik membangun sistem Anda untuk memanfaatkan snapshot.

Contoh dalam Pertanyaan

Dalam contoh yang diberikan dalam pertanyaan, arsitektur tidak benar-benar berbasis peristiwa; berbasis perintah. Memutar perintah menciptakan status sistem. Ini anti-pola dan harus diperbaiki. Sebaliknya, acara utama adalah:

  • Pembeli mengajukan pertanyaan
  • Penjual menjawab pertanyaan

Setiap peristiwa ini dapat "diputar ulang" untuk memberikan kondisi saat ini. Misalnya, dalam tindakan mengajukan pertanyaan, perilaku sistem mungkin mengirim email ke penjual dan menambah unanswered questionpenghitung. Perilaku ini dapat diubah; Namun, fakta bahwa pertanyaan itu diajukan tidak. Demikian pula, sistem dapat mengurangi unanswered questionkonter ketika penjual merespons. Perilaku ini dapat diubah, tetapi kenyataan bahwa penjual merespons tidak.

Sebagian besar sistem sumber acara akan menghitung secara dinamis jumlah pertanyaan yang tidak terjawab dengan memutar ulang arus peristiwa spesifik sebagai respons terhadap kueri.

theMayer
sumber
Ini adalah jawaban yang bagus, terima kasih @ rmayer06
Antony Woods
Dalam contoh lotere ini, Anda mengatakan bahwa "Hanya acara yang dapat menyebabkan perubahan status dalam sistem", tetapi jika acara tersebut "tiket dikeluarkan" (dan mungkin acara mencakup beberapa detail seperti stempel waktu, buyer_id, ticket_id), bagaimana Anda catat nomor referensi tiket jika tidak ada sistem catatan lain yang memproduksi id? Apakah ada sistem CRUD tradisional yang perlu menghasilkan tiket terlebih dahulu sebelum sumber acara dapat merekam fakta sebagai past tense?
Homan
Tindakan mengeluarkan tiket adalah peristiwa dalam kasus ini. Data yang terkait dengan peristiwa adalah apa yang sedang dideskripsikan sebagai peristiwa dalam pertanyaan Anda, yang bermanfaat tetapi secara teknis salah. Selain itu, peristiwa biasanya mewakili holaritas detail, di mana mereka dapat disusun dan didekomposisi relatif tanpa batas di setiap arah.
theMayer
Uh ... kau meniup pikiranku dengan hal holarchy.
Homan
Saya kira apa yang saya pikirkan adalah ini: Di ​​dunia CRUD, terutama Rails, sudah umum memiliki id yang bertambah secara otomatis untuk kunci utama tabel. Kami membuat catatan tanpa mengetahui id, DB menyerahkan saya kembali id ​​tiket. Sekarang pindah ke dunia Event Sourcing, dari apa yang saya baca, acara ini 'direalisasikan' sebelum dipertahankan di DB, dan membutuhkan id agregat. Jadi alih-alih mendapatkan id kembali setelah kegigihan dari DB, sepertinya id unik harus sudah diketahui sehingga dapat digambarkan sebagai keseluruhan. Sepertinya kita harus selalu membuat uuid dan bukan auto-id.
Homan
3

Perintah dan pertanyaan akan tetap ada pada S3 untuk tujuan audit dan pemulihan.

Untuk audit, tentu saja. Untuk memulihkan ? Itu aneh, dan mungkin menyebabkan Anda sakit kepala.

Jika Anda akan menjadi sumber acara, Anda ingin rehydrating state dari peristiwa (hal-hal yang terjadi di masa lalu) bukan perintah. Ini menyelamatkan Anda dari sebagian besar masalah yang terkait dengan perubahan pada implementasi perintah - Anda hanya perlu berurusan dengan perubahan status yang ada.

Versi masih menjadi perhatian. Secara khusus, Anda ingin memastikan bahwa acara Anda yang bertahan setinggi mungkin (representasi DTO, daripada serialisasi langsung dari konsep-konsep di domain Anda). Saat membaca acara dari toko, Anda memiliki kesempatan untuk memperbaruinya seperlunya sebelum menerapkannya ke keadaan rehidrasi.

VoiceOfUnreason
sumber
Ok, jadi saya pikir saran Anda adalah untuk tidak terlalu khawatir tentang memulihkan dari perintah dan lebih banyak tentang dari acara? Sebagai contoh, jika saya mendapatkan perintah di sepanjang baris "tambahkan 10 kacang" maka saya kemudian harus mengeluarkan dan menyimpan acara yang mengatakan "10 kacang ditambahkan. Total baru: 40"?
Antony Woods
Ya itu betul. Setiap perubahan status di entitas sumber acara Anda diwakili oleh satu atau lebih peristiwa; untuk rehydrate, Anda memutar ulang semua acara tersebut secara berurutan.
VoiceOfUnreason
2
Saya tidak menerima jawaban ini tetapi saya ingin berterima kasih atas kontribusi karena sangat penting untuk mengubah pemahaman saya. Saya memilih jawaban rmayer06 hanya karena lebih langsung, bulat dan lebih bermanfaat bagi seseorang yang hanya mengakses pertanyaan ini untuk jawaban cepat.
Antony Woods