اوایل که سیستمهای نرمافزاری تازه داشتن شکل میگرفتن، همه چیز نسبتاً ساده بود. یه دیتابیس داشتیم که اطلاعات رو توش ذخیره میکردیم، تغییرات لازم رو اعمال میکردیم و دوباره ذخیره میکردیم. این روش تا وقتی که سیستمها ساده بودن، کاملاً جواب میداد. اما کمکم که نیازها پیچیدهتر شد، یه سؤال مهم پیش اومد: "چرا و چطور این تغییرات توی دادهها اتفاق افتادن؟"
بیایید با یه مثال ملموس جلو بریم. فرض کنید شما مدیر یه فروشگاه آنلاین هستید. توی روش قدیمی (بدون استفاده از Event Sourcing)، وقتی مشتری یه محصول رو میخره، شما فقط موجودی اون کالا رو توی دیتابیس بهروزرسانی میکنید. مثلاً اگه یه جفت کفش از انبار خریداری بشه، موجودی از ۱۰ به ۹ کاهش پیدا میکنه. اما در این حالت فقط وضعیت نهایی رو میبینید و مشخص نیست چه مراحلی منجر به این تغییر شدن.
Event Sourcing اما یه نگاه جدید به این ماجرا داره. تو این روش، به جای اینکه فقط نتیجه نهایی رو ثبت کنیم، همه اتفاقاتی که باعث تغییر شدن رو ذخیره میکنیم. توی مثال فروشگاه آنلاین، این رویدادها میتونن شامل چیزایی مثل "اضافه شدن محصول به سبد خرید"، "تکمیل پرداخت"، "ارسال محصول" و "کاهش موجودی انبار" باشن. یعنی هر مرحله بهدقت ثبت میشه.
این روش دو تا فایده اصلی داره: اول اینکه ردیابی و رفع اشکال رو خیلی راحتتر میکنه. مثلاً اگه مشتری بگه سفارش به دستش نرسیده، شما میتونید با نگاه کردن به تاریخچه رویدادها بفهمید که دقیقاً سفارش تو کدوم مرحله گیر کرده. دوم هم اینکه این دادههای تاریخی کلی ارزش برای تحلیلهای تجاری دارن، مثلاً اینکه بفهمیم کاربران چه رفتاری تو فرآیند خرید دارن و بتونیم بر اساسش استراتژیهای بازاریابی رو بهینه کنیم.
در نتیجه، Event Sourcing نهتنها یه تاریخچه دقیق از تمام تغییرات سیستم در اختیارمون میذاره، بلکه این امکان رو میده که بتونیم کسبوکارمون رو تحلیل و بهبود بدیم.
Event Sourcing یه الگوی طراحی نرمافزاریه که توش وضعیت یه سیستم به جای اینکه به شکل دادههای ثابت ذخیره بشه، به صورت یه سری رویداد ثبت میشه. این رویدادها تمام تغییراتی که تو طول زمان توی سیستم اتفاق افتادن رو نشون میدن و در واقع حکم "منبع اصلی حقیقت" یا همون Source of Truth رو دارن. هر کدوم از این رویدادها غیرقابل تغییر (Immutable) هستن و اطلاعات کاملی دارن که میتونیم با اونها وضعیت سیستم رو در هر لحظهای از زمان دوباره بازسازی کنیم.
توی این روش، به جای اینکه مستقیم وضعیت فعلی رو ذخیره کنیم، سیستم تمام اتفاقاتی که منجر به وضعیت فعلی شدن رو نگه میداره. برای رسیدن به وضعیت فعلی، فقط کافیه این رویدادها رو یکییکی مرور کنیم؛ به این کار Event Replay میگن. این روش چند تا مزیت بزرگ داره: اول اینکه قابلیت حسابرسی یا Audit کامل رو میده، یعنی هر لحظه میتونیم بررسی کنیم که چه اتفاقی افتاده و چرا. دوم اینکه میتونیم به وضعیتهای گذشته برگردیم، تغییرات رو تحلیل کنیم و حتی اگه جایی اشتباه شده باشه، اون خطاهای قدیمی رو هم اصلاح کنیم.
ببین، این الگو وقتی تو داری یک سیستم رو میسازی، هر تغییری که توی دادهها اتفاق میافته رو نگه میداره. یعنی به جای اینکه فقط حالت نهایی یه چیزی مثل دیتابیس رو داشته باشی، میتونی کل تاریخچه تغییرات رو ذخیره کنی. اینجوری هر زمانی خواستی، میتونی برگردی و ببینی از اول چه اتفاقهایی افتاده و چرا به این نقطه رسیدی.
این کار به چند دلیل خوبه:
در کل، Event Sourcing یه جورایی مثل این میمونه که از همه چیز فیلم بگیری، نه فقط عکس. اینجوری هر لحظهای که بخوای، میتونی برگردی و لحظهبهلحظه ببینی چی شده و چه تصمیماتی گرفته شده.
شیوه کار این الگو بر پایه یه ایده ساده ولی خیلی هوشمندانه بنا شده: اینکه هر تغییری که توی سیستم اتفاق میافته رو بهعنوان یه رویداد ذخیره کنیم. برخلاف روشهای قدیمی که فقط نتیجه نهایی رو توی دیتابیس نگه میداشتن، Event Sourcing مثل یه دوربین فیلمبرداری میمونه که تمام لحظات و تغییرات رو ثبت میکنه و همیشه اونها رو حفظ میکنه.
برای اینکه بهتر متوجه بشیم، فرض کن مدیر یه فروشگاه آنلاین هستی. وقتی مشتری خریدی انجام میده، به جای اینکه فقط «فروش محصول» رو ثبت کنی، سیستم همه مراحل رو به عنوان رویدادهای جداگانه ذخیره میکنه. مثلاً:
"علی هدفون سونی رو به سبد خرید اضافه کرد - ساعت ۱۴:۳۰"
"پرداخت موفق برای سفارش #۱۲۳۴ انجام شد - ساعت ۱۴:۳۵"
"سفارش #۱۲۳۴ تحویل پست داده شد - ساعت ۱۶:۰۰"
این روش مثل اینه که یه ماشین زمان تو سیستم داشته باشی. هر موقع که بخوای، میتونی به عقب برگردی و دقیقاً ببینی چه اتفاقهایی افتاده. با بازپخش این رویدادها (Event Replay)، انگار داری یه فیلم رو تماشا میکنی و میتونی تمام جزئیات یه تراکنش رو از اول تا آخر ببینی و حتی وضعیت سیستم رو در هر لحظهای از زمان بازسازی کنی. این شفافیت و امکان ردیابی دقیق، یکی از باارزشترین ویژگیهای Event Sourcing به حساب میاد.
Event Sourcing یکی از الگوهای معماری نرمافزاری پیشرفتهست که با یه روش خاص توی ثبت و مدیریت دادهها، قابلیتهای فوقالعادهای در اختیار توسعهدهندهها میذاره. با این حال، مثل هر تکنولوژی قدرتمند دیگهای، استفاده از اون به بررسی دقیق مزایا و چالشها نیاز داره تا مطمئن شیم که برای پروژمون بهترین گزینهست.
در نهایت، Event Sourcing یه رویکرد قدرتمند و ارزشمنده که علیرغم پیچیدگیهاش، میتونه تاثیر زیادی روی پروژههای نرمافزاری بذاره. با این حال، کلید موفقیت در استفاده از این الگو، اینه که اول نیازهای پروژه رو دقیق بررسی کنیم و مطمئن شیم که تیم از دانش و مهارت لازم برای مدیریت این معماری برخورداره.
پیادهسازی این الگو با استفاده از پایتون به این صورت کار میکنه که ما به جای ذخیره وضعیت نهایی یک سفارش، تمام رویدادها یا تغییراتی که روی اون سفارش اتفاق میوفته رو ذخیره میکنیم. این روش به ما اجازه میده که همه مراحل و عملیات انجام شده روی سفارش رو ثبت و نگهداری کنیم و در صورت نیاز دوباره اونها رو مرور کنیم. تو این مثال، میخوایم نشون بدیم چطور با استفاده از پایتون میتونیم یه سیستم ساده برای مدیریت سفارشها بسازیم که هر اتفاقی رو که برای هر سفارش افتاده، ثبت کنه و هر زمان نیاز داشتیم، دوباره وضعیت رو بازسازی کنه.
اول از همه، یه کلاس به نام Event تعریف میکنیم که نماینده هر رویدادیه که قراره روی سفارش اتفاق بیفته. این کلاس دو تا ویژگی داره: event_type که نوع رویداد رو نشون میده و data که شامل اطلاعاتیه که به اون رویداد مربوط میشه. به طور مثال، اگه رویداد اضافه کردن یه محصول به سبد خرید باشه، event_type میشه "add_item" و data میشه اطلاعات محصولی که اضافه شده، مثلاً اسم محصول.
class Event:
def __init__(self, event_type, data):
self.event_type = event_type
self.data = data
این کلاس خیلی سادهست و فقط نقش نگهداری اطلاعات هر رویداد رو داره. حالا هر وقت که بخوایم یه رویداد رو به سفارش اضافه کنیم، از این کلاس استفاده میکنیم تا رویداد رو تعریف کنیم.
بعد از تعریف کلاس Event، حالا میریم سراغ ساخت کلاس اصلی برای سفارش که اسمش رو Order میذاریم. این کلاس میتونه رویدادهایی رو که روی یه سفارش اتفاق میوفته، نگهداری و مدیریت کنه. هر سفارش یه order_id داره که شناسه منحصربهفرد اون سفارشه و یه لیست به نام events که همه رویدادهای مربوط به این سفارش رو توش ذخیره میکنیم. وقتی یه رویداد جدید اتفاق میوفته، اون رو به لیست رویدادها اضافه میکنیم.
class Order:
def __init__(self, order_id):
self.order_id = order_id
self.events = [] # لیست رویدادهای سفارش
حالا میتونیم رویدادها رو به این سفارش اضافه کنیم. برای این کار، تابعی به اسم apply_event توی کلاس Order تعریف میکنیم که هر رویداد جدید رو دریافت میکنه و بر اساس نوعش عملیات مناسب رو انجام میده. این تابع به لیست رویدادها همون رویداد جدید رو اضافه میکنه و اگه لازم باشه، پیغامی نشون میده که توضیح میده چه اتفاقی افتاده.
در این تابع apply_event، چک میکنیم که نوع رویداد چیه و بر اساس نوعش، دستور مناسب رو اجرا میکنیم. مثلاً اگه رویداد از نوع "add_item" باشه، نشون میده که یه محصول به سبد خرید اضافه شده؛ اگه "confirm_order" باشه، یعنی سفارش تأیید شده و اگر "make_payment" باشه، مبلغ پرداختشده رو نمایش میده. این کار باعث میشه که هر تغییر بهصورت دقیق و قابل ردیابی ثبت بشه.
def apply_event(self, event):
self.events.append(event)
if event.event_type == "add_item":
print(f"Added {event.data['item']} to the cart.")
elif event.event_type == "confirm_order":
print(f"Order {self.order_id} confirmed.")
elif event.event_type == "make_payment":
print(f"Payment of {event.data['amount']} made.")
elif event.event_type == "ship_order":
print(f"Order {self.order_id} shipped.")
حالا که کلاسهای Event و Order رو تعریف کردیم، میتونیم یه نمونه از سفارش ایجاد کنیم و رویدادهای مختلف رو به اون اضافه کنیم تا ببینیم چطور کار میکنه. فرض کنیم سفارش ما یک لپتاپ داره که مشتری اون رو به سبد خرید اضافه کرده، بعد سفارش رو تأیید کرده، مبلغ رو پرداخت کرده و در نهایت سفارش ارسال شده. برای این کار از کد زیر استفاده میکنیم:
# حالا یک نمونه از Order ایجاد میکنیم
order = Order(order_id=1)
# رویدادها رو یکییکی به سفارش اضافه میکنیم
order.apply_event(Event(event_type="add_item", data={"item": "Laptop"}))
order.apply_event(Event(event_type="confirm_order", data={}))
order.apply_event(Event(event_type="make_payment", data={"amount": 1000}))
order.apply_event(Event(event_type="ship_order", data={}))
در اینجا، هر رویدادی که روی سفارش اتفاق میافته، به ترتیب به لیست رویدادها اضافه میشه. این کار باعث میشه که اگه در آینده نیاز داشتیم بفهمیم چه مراحلی طی شده، به راحتی بتونیم به این لیست مراجعه کنیم.
یکی از بزرگترین مزایای Event Sourcing اینه که به جای اینکه فقط وضعیت نهایی سفارش رو ذخیره کنه، همه تغییراتی که روی سفارش اعمال شده رو ثبت میکنه. این یعنی اگه هر وقت بخوایم بفهمیم دقیقاً چه کارهایی روی یه سفارش انجام شده، میتونیم به راحتی به تاریخچه رویدادها نگاه کنیم و همه چیز رو با جزئیات ببینیم.
از اونجایی که تمام رویدادها به ترتیب ذخیره شدن، اگه سیستم به هر دلیلی دچار مشکل بشه، میتونیم با بازپخش رویدادها وضعیت فعلی رو دوباره بسازیم. این یعنی اگه سیستم کرش کنه یا اطلاعات به هر دلیلی از بین بره، با اجرای دوباره این رویدادها، وضعیت قبلی سفارش رو میتونیم بازسازی کنیم و سیستم رو به حالت عادی برگردونیم.
در این مثال، دیدیم که چطور Event Sourcing به ما کمک میکنه که نهتنها همه تغییرات و رویدادها رو ثبت کنیم، بلکه امکان بازبینی و بازسازی وضعیت سیستم رو هم داریم. این الگو توی سیستمهای پیچیده و بزرگ، مثل سیستمهای مالی یا فروشگاههای آنلاین، خیلی مفیده چون میتونیم همیشه یه تاریخچه کامل از همه تغییرات داشته باشیم و هر وقت نیاز شد، وضعیت قبلی سیستم رو بازسازی کنیم. اینطوری همیشه خیالمون راحته که همه چیز ثبت شده و قابل ردیابی و بازسازی هست.
خب، بیایم یه نگاهی بندازیم به تفاوت الگوی این مقاله با روشهای دیگهای که برای ذخیرهسازی دادهها استفاده میشه. Event Sourcing ایده جذابی داره، ولی همیشه بهترین گزینه نیست. باید ببینیم چه مواقعی ازش استفاده کنیم و چه مواقعی بهتره بریم سراغ روشهای دیگه. بیایم روشهای مختلف رو با هم مقایسه کنیم.
تو ذخیرهسازی سنتی، فقط وضعیت نهایی دادهها رو نگه میداریم. یعنی مثلاً وقتی چیزی توی سیستم تغییر میکنه، وضعیت جدید جایگزین وضعیت قدیمی میشه و دیگه نمیدونیم قبلش چه اتفاقی افتاده. برای همین اگه بخوای بفهمی چه اتفاقی باعث یه مشکل شده، نمیتونی برگردی عقب و دقیق تغییرات رو ببینی. اینجاست که Event Sourcing وارد میشه. توی این الگو، هر رویداد به صورت جداگانه ثبت میشه. یعنی هر تغییری که رخ میده، به عنوان یه رویداد ذخیره میشه و هر وقت خواستی میتونی به عقب برگردی و بفهمی چی شده.
اما خب، یه فرق مهم دیگه هم اینه که توی Event Sourcing حجم دادهها بیشتره. چرا؟ چون هر رویداد رو ذخیره میکنی، پس حجم دیتابیس با گذشت زمان زیاد میشه. ولی تو ذخیرهسازی سنتی فقط وضعیت نهایی رو داری و حجمش کمتره.
حالا برسیم به CQRS. CQRS یه روش دیگهست که یه جورایی با Event Sourcing هم میتونه ترکیب بشه. تو CQRS، فرمانها (که باعث تغییرات میشن) و پرسوجوها (که فقط دادهها رو میخونن) از هم جدا میشن. یعنی هر کدوم از این دو تا مسئولیت جدا دارن و توی دیتابیسهای جداگانه ذخیره میشن.
حالا ممکنه تو CQRS از Event Sourcing استفاده کنی یا از روش سنتی. مثلاً میتونی تو بخش فرمانها از Event Sourcing استفاده کنی که همه تغییرات رو نگه داری و تو بخش پرسوجو فقط دادههای نهایی رو بخونی. اینطوری هم میتونی تغییرات رو نگه داری، هم سریعتر به دادهها دسترسی پیدا کنی.
Snapshotting یه روشیه که تو Event Sourcing خیلی به درد میخوره. وقتی حجم رویدادها خیلی زیاد میشه و بازپخش همه رویدادها برای بازسازی وضعیت زمانبر میشه، میای از وضعیت کلی سیستم یه اسنپشات (عکسلحظهای) میگیری. بعد هر وقت خواستی وضعیت سیستم رو بازسازی کنی، به جای اینکه همه رویدادها رو از اول پخش کنی، میای از آخرین اسنپشات استفاده میکنی و رویدادهای بعد از اون رو بازپخش میکنی.
این کار باعث میشه بازسازی سیستم سریعتر بشه، ولی همچنان پیچیدگی بیشتری نسبت به روشهای سنتی داره. هرچند که استفاده از Snapshotting میتونه به بهینهسازی سیستم کمک کنه.
مورد مقایسه | Event Sourcing | ذخیرهسازی سنتی | CQRS | Snapshotting |
---|---|---|---|---|
مدیریت تغییرات | تمام تغییرات ثبت میشن | فقط وضعیت نهایی نگهداری میشه | دستورات و پرسوجوها جدا هستن | عکسلحظهای از وضعیت سیستم گرفته میشه |
بازگشت به حالت قبلی | امکان بازپخش رویدادها و بازسازی وضعیت | امکان بازگشت به گذشته نیست | میتونه با Event Sourcing ترکیب شه | بازگشت سریعتر با استفاده از اسنپشاتها |
پیچیدگی پیادهسازی | پیچیدهتره و نیاز به مدیریت رویدادها داره | سادهتر و مرسومتره | سادهتره، ولی میتونه پیچیدهتر بشه | پیچیدگی کمتر با بازسازی از اسنپشات |
حجم دادهها | حجم دادهها زیاد میشه | حجم کمتر چون فقط داده نهایی نگهداری میشه | بستگی به مدل دادهها داره | حجم پردازش کمتر با اسنپشاتها |
همونطور که دیدی، Event Sourcing خیلی به درد سیستمهایی میخوره که نیاز به نگهداری تاریخچه تغییرات دارن و سیستمهای پیچیدهای هستن. اما خب، همیشه بهترین گزینه نیست و باید حواست باشه که پیچیدگیها و هزینههای خودشو داره.
Event Sourcing یه الگوی معماریه که به جای ذخیرهسازی فقط وضعیت نهایی دادهها، تمام تغییرات و رویدادها رو به شکل جداگانه ثبت و ذخیره میکنه. این کار باعث میشه که بتونیم تاریخچه کامل هر تغییر رو داشته باشیم و هر وقت لازم شد، وضعیت سیستم رو دوباره بسازیم.
Event Sourcing زمانی استفاده میشه که به تاریخچه کامل رویدادها، امکان برگشت به حالتهای قبلی و تحلیل دقیق تغییرات نیاز داریم. این الگو برای سیستمهای پیچیده مثل سیستمهای مالی، فروشگاهی و بانکی خیلی مناسبه.
توی ذخیرهسازی سنتی، فقط وضعیت نهایی دادهها ذخیره میشه؛ ولی توی Event Sourcing هر تغییر به عنوان یک رویداد ثبت میشه. این یعنی میتونیم به تاریخچه کامل تغییرات دسترسی داشته باشیم و حتی رویدادها رو دوباره بازپخش کنیم.
بله، چون هر تغییری به شکل یه رویداد ذخیره میشه، با گذشت زمان حجم دیتابیس زیاد میشه. برای کنترل این موضوع، میشه از تکنیکهایی مثل آرشیو کردن رویدادهای قدیمی استفاده کرد.
برای پیادهسازی Event Sourcing، به جای ذخیره وضعیت نهایی، باید تغییرات یا رویدادها رو ثبت کنیم. فریمورکها و ابزارهایی مثل Akka، Axon Framework و EventStore میتونن توی پیادهسازی این الگو کمککننده باشن.
بله، Event Sourcing نسبت به روشهای سنتی پیچیدگی بیشتری داره. طراحی و پیادهسازی این الگو نیاز به مهارت و تجربه داره و باید از ابزارها و تکنیکهای مناسب برای ذخیره و بازیابی رویدادها استفاده بشه.
Event Sourcing بیشتر برای سیستمهای پیچیده کاربرد داره. برای سیستمهای کوچیک یا جایی که نیاز به نگهداری تاریخچه دقیق نداریم، پیچیدگی و هزینههای پیادهسازی این الگو ممکنه بهصرفه نباشه.
Event Sourcing یه روش قدرتمنده که بهت اجازه میده تاریخچه دقیق همه تغییرات سیستم رو ثبت کنی. این روش برای سیستمهای پیچیده که نیاز به تحلیل، دیباگ و بازسازی وضعیت دارن فوقالعاده مفیده. البته باید بدونی که با این روش، حجم دیتابیس بزرگتر میشه و طراحی سیستم نیاز به دقت بیشتری داره. اما در نهایت، اگه سیستم پیچیدهای داری و میخوای هیچ اتفاقی رو از دست ندی، Event Sourcing گزینهی خوبیه.
حالا که فهمیدی Event Sourcing چیه، وقتشه بری دست به کار شی و توی سیستمهای خودت پیادش کنی. با ثبت کردن هر رویداد، کنترل کامل رو روی سیستم داری و میتونی هر وقت خواستی، برگردی و بفهمی چی گذشته. به قول معروف، "تاریخچه همیشه حرفی برای گفتن داره!"
دوره الفبای برنامه نویسی با هدف انتخاب زبان برنامه نویسی مناسب برای شما و پاسخگویی به سوالات متداول در شروع یادگیری موقتا رایگان شد: