
فرض کن مسئول یک سیستم ثبت سفارش برای یک فروشگاه اینترنتی هستی. وقتی کاربر دکمه «ثبت سفارش» را میزند، چند مرحله پشتسرهم باید انجام شود:
کم کردن موجودی کالا
مسدود کردن مبلغ سفارش در کیفپول کاربر
ایجاد شماره سفارش
حالا تصور کن سیستم دقیقاً بعد از کم کردن موجودی ولی قبل از مسدود کردن مبلغ کرش کند!
نتیجه؟
موجودی کم شده
مبلغ مسدود نشده
سفارش ناقص
دیتای ناسازگار
و یک دردسر بزرگ! اینجاست که Transaction وارد بازی میشود.
Redis به کمک Transaction این امکان را میدهد که مجموعهای از عملیات را یا کاملاً انجام دهیم یا اصلاً انجام ندهیم — یعنی Atomic.
بهاینترتیب از مشکلات ناشی از خطاها و عملیات همزمان (Concurrent Operations) جلوگیری میکند.
در این مقاله، قدمبهقدم Redis Transaction را بررسی میکنیم و اینکه چگونه کار میکند و چطور میتوانید از آن در پروژههای واقعی خود استفاده کنید.
Transaction در Redis اجازه میدهد چندین Command (مثل SET, INCR, DECR, …) را به صورت یک واحد Atomic اجرا کنید.
به این معنا که:
همهٔ دستورات داخل تراکنش بهطور کامل اجرا میشوند یا هیچکدام اجرا نمیشوند.
اما توجه کنید:
Redis فقط تضمین میکند:
Atomicity
Isolation
اما موارد زیر تضمین نمیشود:
Consistency
Durability
در مقابل، دیتابیسهای رابطهای (مثل PostgreSQL, MySQL) تمامی این ویژگیها را گارانتی میدهند.
بنابراین اگر سرور Redis بلافاصله بعد از دستور EXEC کرش کند، بسته به تنظیمات (مثلاً AOF یا Snapshot)، ممکن است بخشی از داده از دست برود.
ساخت تراکنش در Redis بسیار ساده است.
MULTIهر دستوری که پس از MULTI اجرا شود، وارد یک صف (Queue) میشود.
EXECبا اجرای EXEC، تمام دستورات موجود در صف به ترتیب اجرا میشوند.
اگر هر کدام از دستورات هنگام اجرا خطا داشته باشند، کل تراکنش از بین میرود.
DISCARDاگر بخواهیم تراکنش را لغو کنیم، کافی است دستور DISCARD را اجرا کنیم.
این کار تنها صف را خالی میکند.
ECHO "Start Transaction With Command MULTI" MULTI SET AGE 10 GET AGE ECHO "Execute The Transaction With Command EXEC" EXEC
در این مثال:
دستور MULTI تراکنش را آغاز میکند.
دو دستور SET و GET وارد صف میشوند.
با EXEC، دستورات موجود در صف اجرا میشوند.
اگر به خروجی نگاه کنید، میبینید که هیچ دستوری قبل از EXEC اجرا نمیشود — همه چیز Queue میشود.
برای بهبود خوانایی و درک بهتر، این بخش را به صورت نکات کلیدی میآورم:
Redis تراکنش را خطبهخط اجرا نمیکند؛ همه دستورات بعد از EXEC اجرا میشوند.
تراکنش در Redis Rollback واقعی ندارد. اگر یکی از دستورات اشتباه باشد، فقط قبل از EXEC خطا میگیرید.
اگر زمانی که EXEC اجرا میشود Redis کرش کند، ممکن است بخشی از داده بسته به تنظیمات از دست برود.
تراکنشها در Redis از نوع Optimistic هستند، به همین دلیل دستورات WATCH و مفهوم Optimistic Locking اهمیت زیادی دارند (در مقاله بعدی بررسی میکنیم).
در این مقاله سعی کردم با یک مثال واقعی (سیستم ثبت سفارش فروشگاه آنلاین) به صورت ساده و قابلفهم مفهوم Redis Transaction را توضیح دهم. حالا میدانید:
تراکنشها در Redis چگونه کار میکنند
چه چیزهایی تضمین میشود و چه چیزهایی نه
تفاوت آن با ACID واقعی چیست
و چگونه یک Transaction ساده بسازید
در مقاله بعدی، میرویم سراغ WATCH و Optimistic Locking در Redis و اینکه چطور از Race Condition جلوگیری میکند.