بحث سازگاری در سیستم‌های ذخیره سازی توزیع‌شده

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


مساله:

‏مفهوم تراکنش و سازگاری داده‌ها اساسا در سیستم‌های توزیع‌ شده داده‌ای (Distributed Database Systems) مطرح است. به عنوان مثال وقتی نسخه کپی داده‌ها به صورت فایل در گره‌های مختلف داده‌ای توزیع شده باشند ‏‎[11]‏، مساله مهمی تحت عنوان سازگاری داده‌ها مطرح می‌گردد‏، بدین منظور که به هنگام دسترسی به داده‌های مذکور‏، همه خوانندگان باید تصویر یکسانی از داده‌ها را مشاهده کنند‏، به شکلی که تفاوت معنایی وجود نداشته باشد.

در سیستم‌های توزیع شده هر کدام از گره‌ها دارای وضعیتی هستند‏، مشخصه مهمی که در مورد وضعیت‌ها وجود دارد‏، پویا بودن آنها می‌باشد [6].‎ ‎بدین‎ صورت که با رخداد یک یا چند عملیات بر روی این گره‌ها‏، ممکن است وضعیت در طول زمان تغییر کند [6]‏، به عنوان مثال خواندن و نوشتن نمونه ای از این عملیات می‌باشند. با وجود این اتفاقات‏، معمولا در سیستم‌های توزیع‌شده اثرگذاری تراکنش‌ها بر گره‌های داده‌ای‏، اقدام مهمی در راستای تامین سازگاری می‌باشد‏، به صورتی که تلاش می‌شود وضعیت‌ها دارای شفافیت (Transparency)‎ کافی بوده و از بروز ناسازگاری در عملیات و داده جلوگیری شود. ‏در حالت کلی سازگاری سخت (Strict‎ Consistency) به دنبال تضمین ارائه تصویر داده‌ای یکسان است.


انواع مختلف سازگاری

مفروضات:

فرض می کنیم فرآیند‌های A،B‏ ‎‏و C‎ ‏‎ ‎به‎ صورت مستقل از هم بر روی داده‌ها عمل می‌کنند. این عملیات به صورت ساده‏، خواندن و نوشتن می‌باشد.

  • سازگاری سخت

در صورت اجرای عملیاتی همچون نوشتن یا بروزرسانی‏ توسط یک یا چند فرآیند‏، هر دسترسی به داده‌ها‏‏، پس از عمل بروزرسانی‏، توسط هر کدام از فرآیندها باید به آخرین داده بروز شده منجر شود‏، به نوعی فرآیندها همگی یک تصویر یکسان از داده را دریافت کرده باشند‏،‎ در صورتی که درخواست خواندن قبل از اتمام فرآیند بروزرسانی به گره‌ها ارسال شود‏، تا اتمام فرآیند بروزرسانی‏، مطابق ‏شکل 1 ‎‎عمل خواندن در حالت ‎‎‏بلوکه‎‎‌شده باقی می‌ماند.

شکل 1 - سازگاری سخت [7]
شکل 1 - سازگاری سخت [7]


  • کامیت دو مرحله‌ای

تراکنش های توزیع شده (Distributed Transactions) از یک یا چند تراکنش جزئی (Partial Transactions) تشکیل شده اند که ممکن است هریک از آنها مربوط به یکی از گره‌های سیستم باشد. چنین تراکنش‌هایی معمولا ابتدا توسط سیستم مدیریتی مرکزی (Master Node) دریافت می‌شوند و سپس هرکدام از پرس و جو های داخلی آن به گره مربوطه ارسال می گردد. این مفهوم در شکل 2 نمایش داده شده است.

شکل 2 - مثالی از تراکنش توزیع‌شده [8]
شکل 2 - مثالی از تراکنش توزیع‌شده [8]


اجرای هرکدام از پرس و جوهای جزئی بطور مستقل و محلی بر روی ماشین مربوطه اجرا شده و در انتها نیز نتیجه اجرا به سیستم مدیریتی باز گردانده می شود. سیستم مدیریتی مرکزی منتظر می‌ماند که تمامی تراکنش‌ها اعلام کامیت کنند تا از انجام موفقیت آمیز همه انها اطمینان حاصل نماید. پس از کسب اطمینان کل تراکنش توسط این سیستم مرکزی کامیت (‏‎Commit‎) شده و در نتیجه تغییرات بر روی پایگاه داده توزیع شده اعمال می‌شوند. به این سیاست کامیت کردن، کامیت دو مرحله‌ای (‎‏‏‎Two-phase Commit‎) گفته می شود. توجه داشته باشید که در صورتی که هریک از گره‌ها اعلام شکست نمایند تمامی تراکنش توزیع شده به اصطلاح ‏برگردانده ‎(Rollback)‎ می‌گردد.

معمولاً پایگاه داده‌های‎‎ رابطه‌ای همچون MSSQL‏‏، ‎Oracle‎‏ و ‎MySQL‎ این سطح از سا‎ز‎گاری داده‌ای را تامین می‌کنند. البته در برخی از NoSQL DB ها هم تلاش شده است تا سطحی از سازگاری تامین شود.

  • سازگاری ضعیف

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


  • سازگاری شرطی

سازگاری شرطی فرم خاصی از سازگاری ضعیف است. به این صورت که سیستم ذخیره سازی تضمین می‌کند که اگر بروزرسانی جدیدی بر روی شی داده‌ای اتفاق نیافتد‏، نهایتا همه دسترسی‌ها به آخرین داده بروزرسانی‌شده منجر خواهد شد [12]. این مفهوم در شکل 3 به خوبی نشان داده شده‌است.

سازگاری شرطی [7]
سازگاری شرطی [7]

در این حالت اگر خرابی در سیستم اتفاق نیافتد حداکثر سایز پنجره ناسازگاری براساس فاکتورهایی از قبیل تاخیر در ارتباطات‏، میزان بار سیستم‏، تعداد ‎replication‎‏‌ها می‌تواند مشخص شود.

سیستم نام دامنه (DNS) یکی از مواردی است که تغییرات در دامنه‌ها به مرور زمان اعمال برای همه کاربران اعمال می‌گردد [12]. مهم‌ترین ویژگی سازگاری شرطی پایین‌بودن میزان تاخیر آن است‏، با این ریسک که ممکن است آخرین داده بروزشده را برنگرداند.

سازگاری در انواع پایگاه داده‌ها

برخی از سیستم‌های ذخیره‌سازی امکان انتخاب بین روش‌های مختلف سازگاری از جمله سازگاری سخت و سازگاری شرطی را ‎‏به‎ کاربر استفاده کننده‏، ارائه می‌دهند. به این امکان سازگاری تنظیم پذیر (‎‏‎Tunable Consistency‎) گفته می‌شود.

  • پایگاه‌داده Oracle NoSQL

‏سیستم ‏پایگاه‌داده رابطه‌ای ‎Oracle‎‎‏ به عنوان یکی از معروف‌ترین و پراستفاده ترین پایگاه‌داده رابطه‌ای‏، با پیروی کامل از ‎ACID‎ ‎، سازگاری را به صورت سخت ارائه می‌دهد. اما در نسخه‎ غیر رابطه‌ای (Oracle NoSQL)‏ سازگاری را در سطح عملیات به صورت تنظیم‌پذیر ارائه می‌دهد [10].

  • پایگاه داده DynamoDB

‎‎‏ پایگاه‌داده ‎Dynamo‎DB‎‏ یک سیستم ذخیره‌سازی سرویس گرا ‎NoSQL‎‏ ای می‌باشد‏ که کارایی قابل پیش‌بینی و مقیاس‌پذ‎‏یر‎ی افقی از ویژگی‌های بارز آن می‌باشد ‎‎.[5]

‎‎این سیستم هر دو امکان سازگاری سخت و سازگاری شرطی را به صورت تنظیم‌پذیر‎ ارائه می‌دهد. به عبارتی وقتی تاخیری در شبکه وجود نداشته باشد و حالت خطا رخ ندهد‏، با ارسال پارامترConsistentRead ‎ به هنگام خواندن داده‌ها‏، آخرین داده بروز شده برگشت داده می‌شود. ‏حالت پیش‌فرض خواندن داده‌ها در راستای سرعت بالا ‎‎‏سازگاری شرطی می‌باشد. ‎‏این‎ سیستم ذخیره‌سازی‏، ناسازگاری‌های بروزرسانی را توسط ‏ Vector Clock‎ تشخیص داده‏، اما ترجیح می‌دهد مساله را با مکانیزم‌هایی در سطح کاربر برطرف نماید [9].

  • پایگاه‌داده Cassandra

Cassandra‎‏ یک سیستم ذخیره سازی ستونی است که دارای امکانات کارایی بالا به هنگام درج‏، پایداری بالا‏، ‎‎‏مقیاس‌پذیری افقی‏، پیاده سازی توزیع شده و مقاوم در برابر نقطه شکست مرکزی می‌باشد [9]‎‏.‎

این‎‎ سیستم علاوه بر قابلیت‌های ذکرشده‏، امکان سازگاری را در کیفیت خوب با انتزاعی در سطح ستون‏ ‎ ‎‎‎‏به ازای هر دستور خواندن و نوشتن ‏ارائه‎می‌دهد‏. همچنین ارائه این سطح از سازگاری به صورت تنظیم‌پذیر از ویژگی‌های دیگر این سیستم ذخیره سازی است. ‏شایان ذکر است که تامین سازگاری سخت منوط به تاخیر بالا در پاسخگویی می‌باشد. این مفهوم در ‎‏شکل ‎‎4‎‎‏ نشان داده شده است.

شکل 4 - سازگاری تنظیم‌پذیر [3]
شکل 4 - سازگاری تنظیم‌پذیر [3]


‎‏انواع سطوح سازگاری که ‎Cassandra‎‏ ارائه می‌کند به شرح زیر است ‎‎‎ :[2]

One

‎‎‏در این حالت فقط کافیست یکی از همتاها پاسخ دهد.‎

Two

‎‎‎‏در این حالت با پاسخ دو مورد از همتاها عملیات خواندن ادامه پیدا می‌کند.

Three

در این حالت برای پاسخگویی درست‏، می‌بایست سه مورد از همتاها پاسخ داده باشند.‎

Quorum

در‎این حالت برای اطمینان از اکثریت‏، نیازمند پاسخگویی ‏حداقل 51 ‏درصد ‎از همتاها می‌باشد.‎

All

تمامی‎‎ همتاها می‌بایست پاسخ داده باشند‏، به نوعی سیستم در این حالت به سازگاری سخت میل می‌نماید.‎

Local ‎Quorum

اکثریت‎ همتاها در یک مرکز داده محلی می‌بایست پاسخگو باشند (میزان اکثریت در هر مرکز داده می‌تواند تعیین گردد).‎

Each Quorum

‎‎‏این حالت از سازگاری‏، نیازمند پاسخگویی تنها یکی از همتاها می‌باشد. در حالت خوشه چند-مرکزداده‌ای (Multi-datacenter‎‏)، این مورد تضمین می‌کند که درخواست‌های خواندن به صورت از راه دور اتفاق نمی‌افتد.‎

Any

‎این حالت صرفا برای نوشتن کاربرد دارد و کافیست تنها یک همتا پاسخ دهد‏، البته هماهنگ‌ساز (Coordinator)، نیز باید یک اشاره‌ای‏ از این عملیات دریافت نماید.


  • پایگاه‌داده CouchDB

‎‏این‎ پایگاه‌داده با شعار "یک پایگاه‌داده که مفهوم وب را بپذیرد" شروع به کار کرد. ‎‏مدل داده‌ای این پایگاه‌داده به صورت سندگرا می‌باشد. ارتباط با این پایگاه‌داده از طریق ‎API ‎‏با دستورات ‎GET‎‏ و ‎POST‎‏ به صورت سرویس‏ صورت می‌گیرد. این سیستم با هدف تامین قابلیت اطمینان طراحی و توسعه داده‌شده است. همچنین این پایگاه‌داده‏، جزء معدود سیستم‌های ذخیره سازی است که در محیط موبایل نیز به کار برده می‌شود [4].‎‎

شکل 5 - سازگاری در CouchDB [1]
شکل 5 - سازگاری در CouchDB [1]


در‎رابطه با معماری این پایگاه‌داده بر خلاف پایگاه‌داده های دیگر که ‏به صورت یک گره اصلی و چند گره فرعی Single Master/Multiple Slaves‎ هستند، این پایگاه داده از ‎‏ساختار چند گره اصلی و چند گره فرعی (Multi Masters/Multi Slaves)‎ بهره می‌برد [1].

همچنین ‏این پایگاه‌داده برای دستیابی به سازگاری شرطی از روشی تحت عنوان همتاسازی افزایشی (‎Incremental Replication) ‎بهره می‌برد به این صورت که با تغییر یک سند‏، این تغییرات در بازه زمانی به صورت مکرر در تمامی همتاها کپی می‌گردد [1]. ساختار کلی این روش در شکل 6 نشان داده شده‌است.

شکل 6 - همتاسازی افزایشی [1]
شکل 6 - همتاسازی افزایشی [1]





مراجع

‎‎‏ [1] J Chris Anderson, Jan Lehnardt, and Noah Slater. CouchDB: The Definitive Guide: Time to Relax. ” O’Reilly Media, Inc.”, 2010.

[2] Apache. Apache cassandra, 2017.

[3] Patrick McFadin Software Architect at DataStax. Slideshare-introduction to cassandra, 2017.

[4] Apache CouchDB. couchdb.apache.org, 2017.

[5] Giuseppe DeCandia, Deniz Hastorun, Madan Jampani, Gunavardhan Kakulapati, Avinash Lakshman, Alex Pilchin, Swaminathan Sivasubramanian, Peter Vosshall, and Werner Vogels. Dynamo: amazon’s highly available key-value store. ACM SIGOPS operating systems review, 41(6):205–220, 2007.

[6] Kapali P. Eswaran, Jim N Gray, Raymond A. Lorie, and Irving L. Traiger. The notions of consistency and predicate locks in a database system. Communications of the ACM, 19(11):624–633, 1976.

[7] Google. Balancing strong and eventual consistency with google cloud datastore, 2017.

[8] IBM. Ibm knowledge center - the two-phase commit process, 2017.

[9] Avinash Lakshman and Prashant Malik. Cassandra: a decentralized structured storage system. ACM SIGOPS Operating Systems Review, 44(2):35–40, 2010.

[10] M Seltzer. Oracle nosql database. Oracle White Paper, 2011.

[11] Irving L Traiger, Jim Gray, Cesare A Galtieri, and Bruce G Lindsay. Transactions and consistency in distributed database systems. ACM Transactions on Database Systems (TODS), 7(3):323–342, 1982.

[12] Werner Vogels. Eventually consistent. Communications of the ACM, 52(1):40–44, 2009.