ES / CQRS eşzamanlılık işleme


20

Kısa süre önce CQRS / ES'ye dalmaya başladım çünkü iş yerinde uygulamam gerekebilir. Bir çok sorunu çözeceği için bizim durumumuzda çok umut verici görünüyor.

Bir ES / CQRS uygulamasının basitleştirilmiş bir bankacılık kullanım örneğine nasıl bağlamsallaştırılmış gibi görünmesi gerektiği konusundaki kaba anlayışımı tasvir ettim (para çekme).

ES / CQRS

Özetle, eğer A kişisi biraz para çekerse:

  • bir komut verildi
  • doğrulama / doğrulama için komut teslim edilir
  • doğrulama başarılı olursa bir olay olay deposuna gönderilir
  • toplayıcı, toplamaya değişiklik uygulamak için olayı ayıklar

Anladığım kadarıyla, olay günlüğü gerçeğin kaynağıdır, çünkü GERÇEKLER günlüğü olduğundan, bundan herhangi bir projeksiyon elde edebiliriz.


Şimdi, anlamadığım şey, bu büyük şey şemasında, bu durumda olan şeydir:

  • kural: bir denge negatif olamaz
  • A kişisinin 100e dengesi var
  • A kişisi 100e'lik bir Para Çekme Komutu yayınlar
  • doğrulama geçer ve 100e etkinliğinde MoneyWithdrewEvent yayınlanır
  • bu arada A kişisi 100e'lik başka bir Para Çekme Komutu yayınlar
  • ilk MoneyWithdrewEvent henüz toplanmadı ve bu nedenle doğrulama geçti, çünkü toplamaya karşı doğrulama denetimi (henüz güncellenmedi)
  • 100e MoneyWithdrewEvent başka bir zaman daha yayıyor

==> Dengenin -100e'de tutarsız bir durumdayız ve günlük 2 MoneyWithdrewEvent içeriyor

Anladığım kadarıyla bu sorunla başa çıkmak için birkaç strateji var:

  • a) toplu sürüm kimliğini olay deposundaki olayla birlikte koyun, böylece değişiklik sırasında bir sürüm uyuşmazlığı varsa hiçbir şey olmaz
  • b) doğrulama katmanının bir şekilde bir tane oluşturması gerektiğini ima eden bazı kilitleme stratejileri kullanın

Stratejilerle ilgili sorular:

  • a) Bu durumda, olay günlüğü artık gerçeğin kaynağı değildir, bununla nasıl başa çıkılır? Ayrıca, istemciye geri döndük Tamam çekilmesine izin vermek tamamen yanlıştı, bu durumda kilit kullanmak daha mı iyi?
  • b) Kilitler == kilitlenmeler, en iyi uygulamalar hakkında bir fikriniz var mı?

Genel olarak, eşzamanlılığın nasıl ele alınacağına dair anlayışım doğru mu?

Not: Aynı kişinin bu kadar kısa bir sürede iki kez para çekmesinin imkansız olduğunu anlıyorum, ancak ayrıntılara kaybolmamak için basit bir örnek aldım.


Adım 7'ye kadar beklemek yerine toplamı 4. adımda güncellemiyorsunuz?
Erik Eidt

Yani bu durumda, olay deposunun sadece toplamaları / diğer projeksiyonları yeniden oluşturmak için uygulamaya başlandığında okunan bir günlük olduğunu mu söylüyorsunuz?
Louis F.

Yanıtlar:


19

Bir ES / CQRS uygulamasının basitleştirilmiş bir bankacılık kullanım örneğine nasıl bağlamsallaştırılmış gibi görünmesi gerektiği konusundaki kaba anlayışımı tasvir ettim (para çekme).

Bu, olay kaynaklı bir uygulamanın mükemmel bir örneğidir. Hadi başlayalım.

Her zaman bir komut işlenir ya da (sabırlı, anlayacaktır) aşağıdaki adımlar gerçekleştirilir denenir:

  1. komut bir komut işleyicisine, yani Application layer.
  2. komut işleyicisi Aggregateonu depodan tanımlar ve depodan yükler (bu durumda yükleme, newbir Aggregateörnekleme yaparak, bu toplamanın daha önce yayınlanmış tüm olaylarını getirerek ve bunları Toplamanın kendisine yeniden uygulayarak gerçekleştirilir; Toplama sürümü depolanır olaylar uygulandıktan sonra Agrega nihai durumundadır - yani, cari işlemler dengesi bir sayı olarak hesaplanır)
  3. komut işleyicisi Aggregate, gibi, ilgili yöntemi çağırır Account::withdrawMoney(100)ve verilen olayları toplar MoneyWithdrewEvent(AccountId, 100); hesapta yeterli para yoksa (bakiye <100) bir İstisna ortaya çıkar ve hepsi durdurulur; aksi takdirde bir sonraki adım gerçekleştirilir.
  4. komut işleyici Aggregatedepoya devam etmeyi dener (bu durumda depo, Event Store); o yeni olaylar ekleyerek bunu Event streamancak ve ancak versionbir Aggregatehala zaman oldu biridir Aggregateyüklendi. Sürüm aynı değilse, komut yeniden denenir - 1. adıma gidin . Eğer versionaynı, daha sonra olaylar eklenir Event streamve istemci ile sağlanan Successstatü.

Bu sürüm kontrolüne iyimser kilitleme denir ve genel bir kilitleme mekanizmasıdır. Diğer bir mekanizma, mevcut yazılar tamamlanıncaya kadar diğer yazılar bloke edildiğinde (başlamadığı gibi) kötümser kilitlemedir .

Terim Event stream, aynı Agrega tarafından yayılan tüm olayların etrafında bir soyutlamadır.

Bunun Event store, sadece son durumun değil, bir Toplama'daki tüm değişikliklerin depolandığı başka bir kalıcılık türü olduğunu anlamalısınız .

a) Bu durumda, olay günlüğü artık gerçeğin kaynağı değildir, bununla nasıl başa çıkılır? Ayrıca, istemciye geri döndük Tamam çekilmesine izin vermek tamamen yanlıştı, bu durumda kilit kullanmak daha mı iyi?

Etkinlik mağazası her zaman gerçeğin kaynağıdır.

b) Kilitler == kilitlenmeler, en iyi uygulamalar hakkında bir fikriniz var mı?

Iyimser kilitleme kullanarak hiçbir kilitleri var, sadece komut yeniden denemek.

Neyse, Kilitler! = Kilitlenme


2
AggregateTüm olayları uygulamadığınız bir yerin yüklenmesi ile ilgili bazı optimizasyonlar vardır, ancak Aggregategeçmişte bir noktaya kadar anlık görüntüsünü tutar ve yalnızca o noktadan sonra gerçekleşen olayları uygularsınız.
Constantin Galbenu

Tamam, karışıklığım olay mağazası == olay otobüsünün (kafamı göz önünde bulundurduğum) gerçeğinden kaynaklanıyor. Anlık Aggregategörüntüsünün olması durumunda, anlık görüntü ne zaman güncellenmelidir? Anlık görüntü deposu olay deposu ile aynı mı yoksa olay veriyolundan türetilmiş bir görünüm mü?
Louis F.

Anlık görüntü oluşturma konusunda bazı stratejiler vardır. Bunlardan biri her n olayda bir anlık görüntü oluşturmaktır. Anlık görüntüyü, olaylarla birlikte aynı yerde / kalıcılıkta / veritabanında, aynı taahhütte depolamalısınız. Fikir, anlık görüntünün Aggregate'in sürümüyle güçlü bir şekilde ilişkili olmasıdır.
Constantin Galbenu

Tamam, sanırım bunun üstesinden gelmek için daha net bir vizyonum var. Şimdi son soru, olay otobüsünün sonunda rolü nedir? Agregalar eşzamanlı olarak güncellenirse?
Louis F.

1
Evet, bir RabbitMQ veya olayları okunan modellere eşzamansız olarak göndermek istediğiniz herhangi bir kanalı kullanabilirsiniz, ancak yalnızca etkinlik deposuna devam ettirdikten sonra. Gerçekten de, kalıcı olduktan sonra hiçbir olay validasyonu yapılmaz: olaylar gerçekleşen gerçekleri temsil eder; bir okuma modeli bir şey olmuş olabilir veya olmayabilir, ancak geçmişi değiştiremez.
Constantin Galbenu

1

Bir ES / CQRS uygulamasının basitleştirilmiş bir bankacılık kullanım örneğine nasıl bağlamsallaştırılmış gibi görünmesi gerektiği konusundaki kaba anlayışımı tasvir ettim (para çekme).

Kapat. Sorun "toplu" güncelleme mantığı garip bir yerde olmasıdır.

Daha olağan uygulama, komut işleyicinizin bellekte tuttuğu veri modelinin ve olay deposundaki olay akışının senkronize tutulmasıdır.

Açıklanması kolay bir örnek, komut işleyicisinin olay deposuna eşzamanlı yazma yaptığı ve olay deposuyla bağlantı yazma işleminin başarılı olduğunu gösteriyorsa, modelin yerel kopyasını güncellediği durumdur.

Komut işleyicinin olay deposuyla yeniden senkronize edilmesi gerekiyorsa (dahili modeli mağazanınkine uymadığından), geçmişi depodan yükleyerek ve kendi dahili durumunu yeniden oluşturarak bunu yapar.

Başka bir deyişle, 2 ve 3 okları (varsa) normalde toplu bir mağazaya değil, olay deposuna bağlanır.

toplu sürüm kimliğini olay deposundaki olayla birlikte yerleştirin, böylece değişiklik sırasında sürüm uyuşmazlığı varsa hiçbir şey olmaz

Bunun varyasyonları olağan durumdur - olay akışındaki akışa eklemek yerine , genellikle akıştaki belirli bir konuma PUT koyarız ; bu işlem mağazanın durumuyla uyumlu değilse, yazma başarısız olur ve hizmet uygun hata modunu seçebilir (istemciye başarısız, yeniden deneme, birleştirme ....). Idempotent yazmaları kullanmak, dağıtılmış mesajlaşmada bir takım sorunları çözer, ancak elbette bir idempotent yazmayı destekleyen bir mağazaya sahip olmak gerekir.


Hmm sanırım olay mağazası bileşenini yanlış anladım. Her şeyin içinden geçmesi ve akması gerektiğini düşündüm. Etkinlik mağazam kafka ise ve salt okunursa ne olur? 2. ve 3. adımda tüm mesajları tekrar iletmeyi göze alamam. Görünüşe göre vizyonum bununla
Louis F.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.