Skip to content

Latest commit

 

History

History
211 lines (142 loc) · 36.4 KB

Event Sourcing pattern.md

File metadata and controls

211 lines (142 loc) · 36.4 KB

#‏ Event Sourcing pattern

به‌جای ذخیره وضعیت فعلی داده‌ها در یک حوزه خاص، از یک ذخیره‌کننده در حالت فقط افزودنی (append-only) برای ثبت مجموعه کامل اقدامات انجام شده روی داده‌ها استفاده کنید. ذخیره‌کننده به‌عنوان سیستم ثبت داده‌ها عمل می‌کند و می‌تواند برای تحقق objectها یا domain objects استفاده شود. این ویژگی می‌تواند تسک‌ها را در حوزه‌های پیچیده بدون نیاز به همگام‌سازی در مدل داده و حوزه‌های تجاری آن را ساده‌سازی کند و در ادامه که کارایی (performance)، مقیاس‌پذیری (scalability) و پاسخ‌دهی (responsiveness) را بهبود بخشد. همچنین این ویژگی می‌تواند یکپارچگی برای داده‌های مربوط به تراکنش‌های مختلف را فراهم کند.

   

زمینه و مشکل

  بیشتر برنامه‌ها با انواع داده‌های مختلفی کار می‌کنند و رویکرد معمولی این است که برنامه بتواند وضعیت فعلی داده‌ها را با به‌روزرسانی آنها در زمانی که کاربران با آن کار می‌کنند حفظ کند. به‌عنوان‌مثال، در مدل سنتی create, read, update, delete یا به‌اختصار (CRUD) یک فرایند مربوط به داده‌ها می‌تواند این‌طور باشد که ابتدا داده‌ها را از ذخیره‌گاه بخوانیم سپس تغییراتی در آن‌ها ایجاد کنیم و وضعیت فعلی داده‌ها را با مقادیر جدید به‌روزرسانی کنیم - که اغلب این کار با استفاده از تراکنش‌هایی که داده‌ها را قفل می‌کنند، انجام می‌شود.

    رویکرد CRUD محدودیت‌هایی زیر را دارد:

  *‏ سیستم‌های CRUD عملیات به‌روزرسانی را مستقیماً در برابر یک data store انجام می‌دهند. این عملیات می‌تواند کارایی و کیفیت پاسخگویی را کاهش دهد و به دلیل سربار پردازشی که نیاز دارد، مقیاس‌پذیری (scalability) را محدود کند. *‏ در یک حوزه همکاری مشترک با بسیاری از کاربرانی که هم‌زمان فعالیت می‌کنند، تداخل به‌روزرسانی داده‌ها بیشتر محتمل است؛ زیرا عملیات به‌روزرسانی فقط روی یک مورد از داده‌ها انجام می‌شود. *‏ مگر اینکه مکانیزم محافظتی دیگری وجود داشته باشد که جزئیات هر عملیات را در یک لاگ جداگانه ثبت کند؛ زیرا تاریخچه آن‌ها از بین می‌رود.

   

راه‌حل

  الگوی Event Sourcing رویکردی را برای مدیریت عملیات روی داده‌ها تعریف می‌کند که توسط یک توالی از رویدادها انجام می‌شود که هر یک از آنها فقط در یک ذخیره‌گاه فقط افزودنی (append-only) ثبت می‌شوند. کد برنامه مجموعه‌ای از رویدادها را ارسال می‌کند که به‌طورجدی هر عملی را که روی داده‌ها رخ‌داده است، به ذخیره‌گاه رویداد یا event store می‌فرستد (برای یادآوری event store این مورد به فصل مقدمه مراجعه کنید)، جایی که آنها ذخیره می‌شوند. هر رویداد نشان‌دهنده مجموعه‌ای از تغییرات در داده‌ها است (مانند AddedItemToOrder).

    رویدادها در یک ذخیره‌گاه رویداد که به‌عنوان سیستم ثبت (منبع معتبر داده‌ها) درباره وضعیت فعلی داده‌ها عمل می‌کند. ذخیره‌گاه رویداد معمولاً این رویدادها را منتشر می‌کند تا مصرف‌کنندگان آن رویداد بتوانند از آن وقوع آن مطلع شوند و در صورت نیاز بتوانند به آنها پاسخ‌دهی کنند. برای مثال، مصرف‌کنندگان می‌توانند وظایفی را آغاز کنند که عملیات رویدادها را در سیستم‌های دیگر اعمال می‌کند و هر اقدام مرتبط دیگری را که برای تکمیل عملیات لازم است انجام دهند. توجه داشته باشید که کد برنامه‌ای که رویدادها را تولید می‌کند از سیستم‌هایی که از رویدادها مطلع می‌شوند و آنها را پیام‌ها را دریافت یا subscribe می‌کنند، جدا شده است.

 

نکته: یک materialized view یک جدول شامل داده‌ها است که نتیجه یک کوئری را در خود ذخیره می‌کند. این روش باعث می‌شود که دسترسی به داده‌ها سریع‌تر و کارآمدتر شود، اما به قیمت اشغال فضای بیشتر و احتمال عدم به‌روز بودن برخی از داده‌ها.

  استفاده ساده از رویدادهای منتشر شده (events published) توسط ذخیره‌گاه رویداد برای حفظ materialized view در موجودیت‌ها، برای زمان‌هایی است که فعالیت‌های خاصی در برنامه می‌تواند مقادیر و وضعیت موجودیت‌ها را برای ادغام با سیستم‌های خارجی را دچار تغییر کند. برای مثال، یک سیستم می‌تواند یک materialized view را از تمام سفارش‌های مشتری که برای پر کردن بخش‌هایی از UI استفاده می‌شود، نگهداری کند. این برنامه سفارش‌های جدید را اضافه می‌کند یا آیتم‌های سفارشی را اضافه یا حذف می‌کند و اطلاعات مربوط حمل‌ونقل (shipping) را اضافه می‌کند. رویدادهایی که این تغییرات را توصیف می‌کنند را می‌توان برای به‌روزرسانی materialized view مدیریت و استفاده شوند.

  در هر جایی این امکان برای برنامه‌ها وجود دارد که تاریخچه رویدادها را بخوانند. سپس می‌توانید از آن برای تحقق وضعیت فعلی یک موجودیت با پخش و مصرف تمام رویدادهای مربوط به آن موجودیت استفاده کنید. این فرایند می‌تواند در صورت تقاضا برای تحقق یک شی دامنه(domain object) در هنگام بررسی و پردازش به یک درخواست رخ دهد. همین‌طور این فرایند از طریق یک کار زمان‌بندی شده(scheduled) اتفاق می‌افتد، به‌طوری‌که وضعیت موجودیت می‌تواند به‌عنوان یک materialized view ذخیره شود تا از لایه نمایشی/presentation پشتیبانی کند.

  شکل زیر یک نمای کلی از این الگو را نشان می‌دهد، از جمله برخی از گزینه‌های مورداستفاده برای جریان رویداد یا event stream (یک جریان رویداد یک دنباله مرتب از رویدادها است) مواردی مانند: ایجاد materialized view، ادغام رویدادها با برنامه‌ها و سیستم‌های خارجی و پخش مجدد رویدادها برای ایجاد پیش‌بینی وضعیت فعلی موجودیت‌های خاص است.

  event-sourcing-bounded-context

الگوی Event Sourcing مزایای زیر را ارائه می‌دهد:

  *‏ رویدادها تغییرناپذیر هستند و می‌توانند با استفاده از یک عملیات فقط افزودنی ذخیره شوند. رابط کاربری، گردش کار یا فرایندی که یک رویداد را آغاز کرده است می‌تواند ادامه یابد و کارهایی که رویدادها را مدیریت می‌کنند می‌توانند در پس‌زمینه اجرا شوند. این فرایند، همراه با این واقعیت که در طول پردازش تراکنش‌ها هیچ مغایرتی وجود ندارد، می‌تواند کارایی و مقیاس‌پذیری برنامه‌ها را به‌ویژه برای سطح presentation یا رابط کاربری بسیار بهبود بخشد.

 

نکته: یک ذخیره‌ساز یا ذخیره‌گاه یا data store یک مخزن دیجیتالی است که اطلاعات را در سیستم‌های رایانه‌ای ذخیره و حفظ می‌کند. یک data store می‌تواند یک ذخیره‌سازی متصل به شبکه، یک ذخیره‌سازی ابری توزیع‌شده، یک درایو سخت فیزیکی یا یک ذخیره‌سازی مجازی باشد. این گزینه می‌تواند هم اطلاعات ساختاریافته مانند جداول اطلاعات و هم اطلاعات غیرساختاریافته مانند ایمیل‌ها، تصاویر و ویدئوها را ذخیره کند. سازمان‌ها از data store برای نگهداری، به‌اشتراک‌گذاری و مدیریت اطلاعات در سطح واحدهای کسب‌وکار استفاده می‌کنند

  *‏ رویدادها اشیای ساده‌ای هستند که برخی از اقدامات انجام شده را به همراه هر داده مرتبطی که برای توصیف عمل نمایش‌داده‌شده توسط رویداد موردنیاز است، توصیف می‌کنند. رویدادها مستقیماً یک ذخیره‌ساز داده (data store) را به‌روزرسانی نمی‌کنند. آنها به‌سادگی برای جابه‌جایی در زمان مناسب ثبت می‌شوند. استفاده از رویدادها می‌تواند پیاده‌سازی و مدیریت را ساده کند.

  *‏ رویدادها معمولاً برای متخصص در حوزه data enginner معنی دارند، درحالی‌که عدم تطابق رابطه شی - رابطه (object-relational) می‌تواند جداول پایگاه‌داده پیچیده را به‌سختی تحلیل کند. جدول‌ها معمولاً دارای ساختارهای مصنوعی هستند که وضعیت فعلی سیستم را نشان می‌دهند، نه رویدادهایی که در سیستم رخ‌داده‌اند.

  *‏ Event Sourcing می‌تواند به جلوگیری از ایجاد تداخل به‌روزرسانی‌های هم‌زمان کمک کند، زیرا از نیاز به به‌روزرسانی مستقیم اشیای در data store جلوگیری می‌کند. بااین‌حال، domain model همچنان باید به‌گونه‌ای طراحی شود که از خود در برابر درخواست‌هایی که ممکن است منجر به وضعیت ناسازگار شود، محافظت کند.

  *‏ استفاده از ذخیره‌سازی فقط افزودنی (append-only storage)، ردیابی رویدادهای یک مسیر قابل‌ردیابی را فراهم می‌کند که می‌توان از آن برای نظارت یا مانیتورینگ بر اقدامات انجام شده روی یک ذخیره‌سازی داده استفاده کرد. می‌توان با پخش مجدد رویدادها در هر زمان دلخواه، وضعیت فعلی را به‌عنوان یک materialized views بازسازی کند که در نهایت می‌تواند به تست و اشکال‌زدایی سیستم کمک کند. علاوه بر این، الزام به استفاده از رویدادهای جبران‌کننده (compensating events) برای لغو تغییرات می‌تواند تاریخچه‌ای از تغییراتی را ارائه دهد. همین‌طور اگر مدل فقط حالت فعلی را ذخیره می‌کرد، امکان بازگشت به رویداد گذشته وجود نداشت. لیست رویدادها همچنین می‌تواند برای تجزیه‌وتحلیل عملکرد برنامه و تشخیص روندهای رفتار کاربر استفاده شود یا می‌توان از آن برای به‌دست‌آوردن اطلاعات مفید تجاری دیگر استفاده کرد.

  *‏ در واقع ذخیره‌گاه رویداد امکان وقوع رویدادها را افزایش می‌دهد و تسک‌ها در پاسخ به آن رویدادها عملیات خاص خود را انجام می‌دهند. این جداسازی وظایف از رویدادها، امکان انعطاف‌پذیری(flexibility) و توسعه‌پذیری(extensibility) را فراهم می‌کند. تسک‌ها در مورد نوع رویداد و داده‌های رویداد مطلع هستند؛ اما در مورد عملیاتی که رویداد را آغاز کرده است، اطلاعاتی ندارند. علاوه بر این، چندین تسک می‌تواند هر رویداد را مدیریت کند. این امکان ادغام آسان با سایر سرویس‌ها و سیستم‌هایی را فراهم می‌کند که فقط به رویدادهای جدید مطرح شده توسط event store گوش می‌دهند. بااین‌حال، رویدادهای Event Sourcing معمولاً سطح بسیار پایینی دارند و ممکن است لازم باشد به‌جای آن رویدادهای یکپارچه‌سازی خاصی ایجاد شود.

 

Event Sourcing معمولاً با الگوی CQRS با انجام تسک‌های مدیریت داده در پاسخ به رویدادها و با materializing viewها از طریق رویدادهای ذخیره شده ترکیب می‌شود.

 

مسائل و ملاحظات

هنگام تصمیم‌گیری در مورد نحوه اجرای این الگو به نکات زیر توجه کنید: سیستم فقط زمانی به طور یکپارچگی تدریجی یا eventually consistent (برای توضیح بیشتر این مورد به فصل مقدمه رجوع کنید) می‌شود که با بازپخش رویدادها، materialized views شده یا پیش‌بینی‌هایی از داده‌ها را ایجاد کند. بین اینکه یک برنامه رویدادهایی را به‌عنوان نتیجه رسیدگی به یک درخواست به ذخیره‌ساز رویداد اضافه کند، رویدادها منتشر شوند و مصرف‌کنندگان رویدادها آن‌ها را پردازش کنند، تأخیری وجود دارد. در این دوره، رویدادهای جدیدی که تغییرات بیشتری را در موجودیت‌ها توصیف می‌کنند، ممکن است به ذخیره‌گاه رویداد رسیده باشند. سیستم باید طوری طراحی شود که در این سناریوها با یکپارچگی تدریجی، سازگار باشد.

     

توجه داشته باشید
برای اطلاعات در مورد پایداری شرطی (eventual consistency) به [Data Consistency Primer](https://learn.microsoft.com/en-us/previous-versions/msp-n-p/dn589800(v=pandp.10)) یا فصل مقدمه مراجعه کنید.

 

    یک ذخیره‌گاه رویداد در واقع یک منبع دائمی از اطلاعات است و بنابراین داده‌های رویداد هرگز نباید به‌روزرسانی شوند. تنها راه برای به‌روزرسانی یک موجودیت برای لغو تغییرات یا افزودن یک رویداد جبران‌کننده جدید به ذخیره‌گاه است. اگر قالب یا فرمت رویدادهایی با ماندگاری زیاد، نیاز به تغییر داشته باشد، شاید در طول مرحله مهاجرت(migration)، ترکیب رویدادهای موجود در ذخیره‌گاه با نسخه جدید دشوار باشد. ممکن است لازم باشد همه رویدادهایی که تغییرات ایجاد می‌کنند تکرار شوند تا با فرمت جدید مطابقت داشته باشند یا باید رویدادهای جدیدی اضافه کنید که از فرمت جدید استفاده می‌کنند. برای حفظ هر دو فرمت رویداد قدیمی و جدید، از یک version stamp در هر نسخه از طرح رویداد (event schema) استفاده کنید.

  برنامه‌های چندرشته‌ای (Multi-threaded) و چند نمونه (multiple instances) از برنامه‌ها ممکن است رویدادها را در ذخیره‌گاه داده یا event store ذخیره کنند. سازگاری رویدادها در event store بسیار مهم است، مانند ترتیب رویدادهایی که بر یک موجودیت خاص تأثیر می‌گذارند (ترتیبی که تغییرات روی یک موجودیت رخ می‌دهد بر وضعیت فعلی آن تأثیر می‌گذارد). افزودن timestamp به هر رویداد می‌تواند به جلوگیری از این مشکلات کمک کند. یکی دیگر از روش‌های رایج، حاشیه‌نویسی(annotate) هر رویداد ناشی از یک درخواست با یک شناسه افزایشی (incremental identifier) است. اگر دو اقدام برای افزودن رویدادها برای یک موجودیت به طور هم‌زمان تلاش کنند، ذخیره‌گاه رویداد می‌تواند رویدادی را که با شناسه موجودیت یا entity خاص از قبل وجود داشته و با شناسه رویداد مطابقت دارد را رد کند. هیچ رویکرد استاندارد یا مکانیزم‌های موجود مانند کوئری‌های SQL برای خواندن رویدادها برای به‌دست‌آوردن اطلاعات آن‌ها وجود ندارد. تنها داده‌ای که می‌توان استخراج کرد، جریانی از رویدادها با استفاده از یک شناسه رویداد (event identifier) به‌عنوان یک معیار است. شناسه رویداد معمولاً به موجودیت‌های جداگانه نگاشت می‌شود. وضعیت فعلی یک موجودیت را می‌توان تنها با پخش مجدد همه رویدادهایی که به آن مربوط می‌شود در برابر وضعیت اصلی آن موجودیت تعیین کرد.

  طول هر جریان رویداد (event stream) بر مدیریت و به‌روزرسانی سیستم تأثیر می‌گذارد. اگر جریان‌ها (streamها) بزرگ هستند، در فواصل زمانی خاص مانند تعداد مشخصی از رویدادها، snapshotهای فوری ایجاد کنید. وضعیت فعلی موجودیت را می‌توان از snapshot و با پخش مجدد هر رویدادی که پس از آن نقطه از زمان رخ‌داده است به دست آورد. برای اطلاعات بیشتر در مورد ایجاد snapshot از داده‌ها، به Primary-Subordinate Snapshot Replication مراجعه کنید. حتی اگر منبع رویداد یا event source (برای مطالعه بیشتر در مورد event source به بخش مقدمه رجوع کنید) شانس به‌روزرسانی‌های متناقض داده‌ها را به حداقل می‌رساند، برنامه همچنان باید بتواند با ناهماهنگی‌هایی که از یکپارچگی تدریجی (eventual consistency) و فقدان تراکنش‌ها ناشی می‌شود، مقابله کند. به‌عنوان‌مثال، رویدادی که نشان‌دهنده کاهش موجودی انبار است ممکن است در حین ثبت سفارش برای آن کالا به ذخیره‌گاه داده برسد. این وضعیت منجر به نیاز به تطبیق این دو عملیات، یا از طریق مشاوره به مشتری یا ایجاد یک برگشت‌خوردن سفارش می‌شود. انتشار رویداد (Event publication) ممکن است حداقل یک‌بار رخ‌داده باشد، بنابراین مصرف‌کنندگان رویدادها باید idempotent باشند (یک عملیات در نرم‌افزار زمانی idempotent است که انجام چندین بار آن تأثیر یکسانی را داشته باشد. به‌عبارت‌دیگر، نتیجهٔ یک عملیات idempotent مستقل از تعداد دفعاتی است که آن عملیات اجرا می‌شود). اگر رویداد بیش از یک‌بار اجرا شود، در نتیجه آنها نباید به‌روزرسانی شرح داده شده در یک رویداد را دوباره اعمال کنند. چندین نمونه از یک مصرف‌کننده می‌تواند موجودیت خاصی را حفظ و تجمیع کند، مانند تعداد کل سفارش‌های انجام شده. فقط یک‌بار باید در افزایش تجمعی موفق شود و آن هم زمانی است که یک رویداد سفارشی رخ می‌دهد. درحالی‌که این نتیجه یک مشخصه کلیدی منبع رویداد یا event sourcing نیست، اما تصمیم معمول پیاده‌سازی است.

    ذخیره‌ساز رویداد یا event storage انتخاب شده باید از بار رویداد ایجاد شده توسط برنامه شما پشتیبانی کند.

 

برای اطلاعات بیشتر به در مورد event storage به فصل مقدمه رجوع کنید

  مراقب سناریوهایی باشید که در آن پردازش یک رویداد شامل ایجاد یک یا چند رویداد جدید می‌شود؛ زیرا این امر می‌تواند باعث ایجاد یک حلقه بی‌نهایت شود.

 

چه زمانی از این الگو استفاده کنیم؟

  از این الگو در حالت زیر استفاده کنید: *‏ زمانی که می‌خواهید هدف یا دلیلی را در داده‌ها ثبت کنید. به‌عنوان‌مثال، تغییرات یک customer entity را می‌توان به‌عنوان یک سری از انواع رویدادهای خاص، مثلاً برای داده‌های فردی که در پایگاه‌داده ثبت شده است مواردی مثل؛ تغییر محل سکونت، حساب بسته، یا متوفی را ثبت کرد.

*‏ زمانی که برای به‌حداقل‌رساندن یا اجتناب‌کردن از به‌روزرسانی داده‌ها که ممکن است منجر به تداخل داده‌ای شود، ضروری است.

*‏ هنگامی که می‌خواهید رویدادهایی را که رخ می‌دهند ضبط کنید سپس آنها را دوباره پخش کنید تا وضعیت یک سیستم بازیابی شود یا تغییرات را به عقب برگردانید (roll back) یا لاگ و گزارش خاصی را نگه دارید. به‌عنوان‌مثال، هنگامی که یک کار شامل چندین مرحله است، ممکن است لازم باشد اقداماتی را برای بازگرداندن به‌روزرسانی‌ها انجام دهید و سپس برخی از مراحل را مجدداً پخش کنید تا داده‌ها به حالت ثابت بازگردند. *‏ استفاده از رویدادها برابر با یک ویژگی طبیعی و عملکردی هر برنامه‌ای است و به توسعه یا تلاش اضافی کمتری نیاز دارد.

*‏ زمانی که نیاز دارید فرایند ورودی یا به‌روزرسانی داده‌ها را از تسک‌های موردنیاز برای استفاده از این عملیات جداسازی کنید. این تغییر ممکن است برای بهبود عملکرد رابط کاربری یا توزیع رویدادها به سایر شنوندگانی(listeners) باشد که هنگام وقوع رویدادها، فعالیت خاصی را انجام می‌دهند. به‌عنوان‌مثال، می‌توانید یک سیستم حقوق و دستمزد را با یک وب‌سایت اظهارنامه مالی ادغام کنید. رویدادهایی که توسط ذخیره‌ساز رویداد (event store) در پاسخ به‌روزرسانی داده‌های ایجاد شده در وب‌سایت مطرح می‌شود که توسط وب‌سایت و سیستم حقوق و دستمزد استفاده می‌شود.

*‏ هنگامی که می‌خواهید ویژگی انعطاف‌پذیری(flexibility) در برنامه را داشته باشید تا بتوانید فرمت materialized مدل‌ها و داده‌های entity را در صورت تغییر نیازمندی‌ها تغییر دهید، یا - وقتی با CQRS استفاده می‌شود - باید یک read model یا viewهایی را که داده‌ها را نشان می‌دهند تطبیق دهید.

*‏ هنگامی که با الگوی CQRS استفاده می‌شود، استفاده از یکپارچگی تدریجی(eventual consistency) قابل‌قبول است به‌خصوص زمانی که read model به‌روزرسانی می‌شود.

    این الگو ممکن است در شرایط زیر مفید نباشد: *‏ برنامه‌های کوچک یا ساده، سیستم‌هایی که business logic کمی دارند یا اصلاً logic ندارند یا سیستم‌‌های که با مکانیزم‌‌های مدیریت داده‌‌های سنتی CRUD به‌خوبی کار می‌کنند.

*‏ سیستم‌‌هایی که در آنها به‌روزرسانی‌‌های بی‌درنگ و یکپارچگی زیاد برای داده‌ها موردنیاز است.

*‏ سیستم‌‌هایی که در آن ردیابی اجرای برنامه، تاریخچه عملکرد برنامه و قابلیت‌‌هایی برای roll back و اجرای مجدد فعالیت‌‌های برنامه، ضروری نیست.

*‏ سیستم‌‌هایی که در آن‌ها احتمال تداخل و تضاد هنگام به‌روزرسانی داده‌ها کم است. به‌عنوان‌مثال، سیستم‌هایی که عمدتاً داده‌ها را به‌جای به‌روزرسانی وضعیت آن داده‌ها، به‌صورت تکراری آنها داده‌ها را اضافه می‌کنند.

 

مثال

یک سیستم مدیریت کنفرانس نیاز به ردیابی تعداد رزروهای تکمیل شده برای یک کنفرانس دارد. به‌این‌ترتیب وقتی یک شرکت‌کننده سعی می‌کند موردی را رزرو کند، می‌تواند بررسی کند که آیا هنوز صندلی خالی در دسترس است؟ این سیستم می‌تواند تعداد کل رزروهای یک کنفرانس را حداقل به دو روش ذخیره کند:

  *‏ این سیستم می‌تواند اطلاعات مربوط به تعداد کل رزروها را به‌عنوان یک موجودیت جداگانه در پایگاه‌داده‌ای که اطلاعات رزرو را در خود نگه می‌دارد، ذخیره کند. همان‌طور که رزرو انجام می‌شود یا لغو می‌شود، سیستم می‌تواند این تعداد را در صورت لزوم افزایش یا کاهش دهد. این رویکرد از نظر تئوری ساده است، اما اگر تعداد زیادی از شرکت‌کنندگان در تلاش برای رزرو صندلی در مدت‌زمان کوتاهی باشند، می‌تواند باعث مشکلات مقیاس‌پذیری شود. به‌عنوان‌مثال، در لحظات مربوط به آخرین روز یا قبل از بسته‌شدن دوره رزرو دچار خطا شود. *‏ این سیستم می‌تواند اطلاعات مربوط به رزرو و لغو را به‌عنوان رویدادهایی که در event store برگزار می‌شود ذخیره کند. سپس می‌تواند تعداد صندلی‌های موجود را با پخش مجدد این رویدادها محاسبه کند. این رویکرد به دلیل تغییرناپذیری رویدادها می‌تواند مقیاس‌پذیرتر باشد. سیستم فقط باید بتواند داده‌ها را از event store بخواند یا داده‌ها را به event store اضافه کند. اطلاعات رویداد در مورد رزرو و لغو آن هرگز اصلاح نمی‌شود.

  نمودار زیر نشان می‌دهد که چگونه می‌توان زیرسیستم رزرو صندلی سیستم مدیریت کنفرانس را با استفاده از Event Sourcing پیاده‌سازی کرد.

  event-sourcing-overview

    ترتیب اقدامات برای رزرو دو صندلی به شرح زیر است:

  ۱- رابط کاربری دستور رزرو صندلی برای دو شرکت‌کننده را صادر می‌کند. فرمان توسط یک کنترل‌کننده فرمان جداگانه مدیریت می‌شود. همین‌طور بخشی از منطق برنامه که از رابط کاربری جدا شده و مسئول رسیدگی به درخواست‌های ارسال شده به‌عنوان دستورات است. ۲- مجموعه‌ای حاوی اطلاعات مربوط به تمام رزروهای کنفرانس با پرس‌وجو از رویدادهایی که رزروها و لغوها را توصیف می‌کنند ساخته می‌شود. این مجموعه SeatAvailability نامیده می‌شود و در یک domain model قرار می‌گیرد که روش‌هایی را برای کوئری و اصلاح داده‌ها در مجموعه نشان می‌دهد.

 

برخی از بهینه‌سازی‌هایی که باید در نظر گرفته شوند، استفاده از snapshotها (به‌طوری که نیازی به پرس‌وجو یا کوئری و پخش مجدد فهرست کامل رویدادها برای به‌دست‌آوردن وضعیت فعلی مجموع نباشید)، و نگهداری یک کپی ذخیره‌شده از جمع، بیانگر حالت‌های مختلف در حافظه است.

    ۳- کنترل‌کننده فرمان روشی را فراخوانی می‌کند که توسط domain model نمایش‌داده‌شده است تا رزروها را انجام دهد. ۴- مجموع SeatAvailability رویدادی را ثبت می‌کند که شامل تعداد صندلی‌های رزرو شده است. دفعه بعد که مجموع رویدادها را اعمال می‌کند، از همه رزروها برای محاسبه تعداد صندلی‌های باقی‌مانده استفاده می‌شود. ۵- سیستم رویداد جدید را به لیست رویدادهای event store اضافه می‌کند.

  اگر کاربر یک صندلی را لغو کند، سیستم فرایند مشابهی را دنبال می‌کند به جز اینکه کنترل‌کننده فرمان دستوری را صادر می‌کند که یک رویداد لغو صندلی ایجاد می‌کند و آن را به event store اضافه می‌کند. استفاده از event store علاوه بر فراهم‌کردن زمینه بیشتر برای مقیاس‌پذیری، تاریخچه کامل یا دنباله قابل‌ردیابی از رزروها و لغوهای یک کنفرانس را نیز ارائه می‌دهد. event store مربوط رویدادها گزینه دقیقی است. نیازی به تداوم انباشته‌ها به روش دیگری نیست؛ زیرا سیستم می‌تواند به‌راحتی رویدادها را دوباره پخش کند و وضعیت را به هر نقطه از زمان بازگرداند.

 

اطلاعات بیشتر در مورد این مثال را می‌توانید در معرفی Event Sourcing در مقدمه این فصل بیابید.

 

قدم بعدی

*‏ عدم تطابق رابطه شی - رابطه‌ای یا Object-relational impedance mismatch

*‏ Data Consistency Primer. هنگامی که از Event Sourcing با یک read store جداگانه یا materialized views استفاده می‌کنید، داده‌‌های خوانده شده معمولاً به‌صورت لحظه‌ای پایدار نیستند. در عوض، داده‌ها فقط در حال شرطی پایدار (eventually consistent) خواهند بود. این مقاله مسائل مربوط به حفظ ثبات در داده‌های توزیع شده را خلاصه می‌کند.

*‏ Data Partitioning Guidance. هنگامی که از Event Sourcing برای بهبود مقیاس‌پذیری، کاهش تداخل‌ها و بهینه‌سازی کارایی برنامه استفاده می‌کنید، معمولاً داده‌ها تقسیم‌بندی می‌شوند. این مقاله نحوه تقسیم داده‌ها به پارتیشن‌های مجزا و مسائلی که ممکن است ایجاد شود را شرح می‌دهد. وبلاگ مارتین فاولر:

*‏ - Event Sourcing

  *‏ - Snapshot on Martin Fowler's Enterprise Application Architecture website

 

منابع مرتبط

  *‏ الگوی Command and Query Responsibility Segregation (CQRS) pattern. در واقع write store است که منبع دائمی اطلاعات را برای پیاده‌سازی CQRS فراهم می‌کند که اغلب مبتنی بر پیاده‌سازی الگوی منبع‌یابی رویداد است. نحوه تفکیک عملیات خواندن داده‌ها در یک برنامه را از عملیات به‌روزرسانی داده‌ها با استفاده از رابط‌های جداگانه توضیح می‌دهد.

*‏ Materialized View pattern. ذخیره داده مورداستفاده در سیستمی که مبتنی بر - Event Sourcing است، معمولاً برای کوئری‌های کارآمد و دقیق مناسب نیست. در عوض، یک رویکرد رایج این است که در فواصل زمانی منظم یا زمانی که داده‌ها تغییر می‌کنند، viewهای ازپیش‌ساخته شده داده‌ها را تولید شود.

*‏ الگوی تراکنش جبرانی (Compensating Transaction pattern). داده‌های موجود در event sourcing store به‌روزرسانی نمی‌شود. در عوض، ورودی‌های جدیدی اضافه می‌شوند که وضعیت موجودیت‌ها را به مقادیر جدید انتقال می‌دهند. برای معکوس کردن یک تغییر، از ورودی‌های جبرانی استفاده می‌شود؛ زیرا امکان معکوس کردن تغییر قبلی وجود ندارد. در واقع این مورد نحوه واگرد کاری که توسط عملیات قبلی انجام شده است را شرح می‌دهد.