محمد قلع گر
محمد قلع گر
خواندن ۴ دقیقه·۲ سال پیش

بررسی راهکارهای ذخیره سازی تغییرات دیتا


معمولا آخرین نسخه دیتا در بانک اطلاعاتی ذخیره می شود و اگر به تغییرات دیتا از ابتدا تاکنون نیاز داشته باشیم بایستی با یک راهکاری تغییرات را ذخیره کنیم

چرا به تغییرات دیتا نیاز داریم ؟

- نیازمندی Debug : برخی مواقع ممکن است وضعیت فعلی دیتا براساس یک باگ در نرم افزار به وجود آمده باشد و برای رفع باگ نیاز داریم وضعیت قبلی دیتا رو داشته باشیم تا شبیه سازی درستی انجام بدیم

- امکان Undo : برخی مواقع به دلیل انصرات کاربر از یک عملیات یا صلاحدید های دیگر نیاز به بازگشت به وضعیت قبلی داریم که بایستی دیتای قبلی در دسترس باشد .

- نمایش History : برای امور پشتیبانی و یا در برخی از بیزنس ها نیاز به مشاهده ی تغییرات دیتا از ابتدا تاکنون برای نیروی پشتیبان یا خود کاربر می باشد .


راهکارهای ذخیره سازی تغییرات :

- روش Action Log : در این روش ، آدرس و دیتای متدهایی که توسط کاربر فراخوانی شده است ذخیره می شود

- روش DataBase Log : در این روش ، از هر ردیف جداول دیتابیس قبل از تغییر ، یک کپی در جدول لاگ ایجاد می کنیم .

- روش Domain Event : در این روش ، تغییراتی که در Aggregate ها اتفاق می افتاد در یک جدول ذخیره می شود .


Action Log :

روش پیاده سازی :

با استفاده از یک Action Filter یا Middleware اطلاعات Request شامل Url , Headers , Body و همچنین اطلاعات Response شامل Status Code , Headers , Body را ذخیره سازی می کنیم .

براساس نیازمندی می توانیم اطلاعات Command ها یا Query ها یا هر دو را براساس HttpMethod تفکیک و ذخیره سازی کنیم .

ضمنا امکان لاگ کردن همه ی درخواست ها و یا صرفا خطاها براساس Status Code خواهد بود .

محل ذخیره سازی پیشنهادی برای این روش Elastic می باشد که با استفاده از ابزار Kibana امکان نمایش و جستجوی لاگ ها را فراهم می کند .


مزایا :

- امکان ذخیره سازی لاگ Query ها

- امکان ذخیره سازی لاگ خطاهای درخواست / سرور که منجر به تغییر دیتا نشده اند

- امکان جستجوی لاگ براساس متدها

- سادگی پیاده سازی


معایب :

- عدم امکان ایجاد ارتباط دقیق بین لاگ ها و دیتاهای جداول مختلف

- حجم زیاد لاگ ها به دلیل نگهداری کلیه ی دیتای ارسالی / دریافتی متدها

- عدم امکان Undo



DataBase Log :

روش پیاده سازی :

به ازای هر جدول ، یک Trigger روی Insert , Update , Delete می گذاریم و کل فیلدهای جدول را در جدول دیگری همراه با id ردیف تغییر کرده ذخیره می کنیم دیتای لاگ ممکن است به صورت serilize شده در یک فیلد قرار گیرد (امکان نگهداری لاگ همه ی جداول در یک جد.ول) و یا به ازای هر فیلد در جدول اصلی ، یک فیلد در جدول لاگ داشته باشیم (نیاز به جدول لاگ مجزا به ازای هر جدول) .

امکان پیاده سازی در داخل نرم افزار نیز وجود دارد به عنوان مثال در Ef Core می توانیم متد SaveChange را بازنویسی کرده و با استفاده از Change Tracker تغییرات را دریافت و در جدول جداگانه ای ذخیره نموده و با یک Transaction روی دیتابیس اعمال نماییم .

در صورت نیاز به Undo فقط کافیست ردیف لاگ مورد نظر به جای دیتای اصلی در دیتابیس قرار گیرد.


مزایا :

- ارتباط دقیق بین ردیف های دیتابیس و لاگ تغییرات

- امکان انجام خودکار با استفاده از Trigger ها

- سادگی پیاده سازی

- امکان Undo


معایب :

- حجم زیاد لاگ ها به دلیل نگهداری کلیه ی دیتا در هر تغییر

- پیچیدگی تشخیص دقیق تغییرات در هر عملیات



Domain Event :

روش پیاده سازی :

این روش مناسب معماری های مبتنی بر رویکرد DDD می باشد . در هر متد Aggregate Root یک Domain Event مجزا منتشر می شود که شامل دیتای دریافتی در آن متد می باشد و Domain Event ها همراه با ذخیره سازی سایر دیتا ها در جدول جداگانه ای شامل AggregateId , AggregateType , EventType , EventData , Time , UserId ذخیره می شوند .

برای افزایش خوانایی ایونت ها می توانیم متد ToString داخل هر نوع ایونت را بازنویسی کرده و براساس نوع ایونت و دیتای ورودی یک متن خوانا تولید نماییم و هنگام نمایش ایونت ها به جای دیتای خام ، این متن را نمایش دهیم .

در صورت نیاز به امکان Undo و بازگشت به نسخه خاصی از دیتا ، بایستی Aggregate Root براساس ساختار Event Sourcing پیاده سازی شده باشد و لیست ایونت ها از ابتدا تا زمانی که دیتا بایستی به آن نسخه تغییر کند از دیتابیس دریافت و به ترتیب روی Aggregate Root اعمال می گردد .


معایب :

- پیچیدگی پیاده سازی (مناسب معماری های خاص)

- عدم امکان ذخیره سازی لاگ Query ها


مزایا :

- ارتباط دقیق بین لاگ تغییرات و Aggregate ها

- تشخیص دقیق تغییرات در هر عملیات

- امکان Undo (نیاز به ساختار Event Sourcing)



رویکرد پیشنهادی :

اگر از معماری های مبتنی بر DDD استفاده می کنید روش Domain Event را برای ذخیره سازی تغییرات دیتا استفاده کنید و خطاهای 500 را با استفاده از روش Action Log جهت دیباگ مشکلات نرم افزار ذخیره کنید .

ذخیره سازی لاگ کوئری ها به دلیل حجم زیاد ، توصیه نمی شود و اگر نیازمندی آماری دارید استفاده از prometheus توصیه می شود .

در صورت نیاز می توانید خطاهای 400 را برای رفتارسنجی کاربران ذخیره نمایید .



ذخیره سازیlogdomain eventdatabasecqrs
شاید از این پست‌ها خوشتان بیاید