Last Write Wins (LWW) — استراتژی حل تعارض است که در آن سیستم بهطور خودکار نسخهای از دادهها را با جدیدترین نشانگر زمان انتخاب میکند. این سادهترین مکانیسم همگرایی در سیستمهای موبایل توزیعشده است: از دو نوشته مترقازب، نوشته جدیدتر پیروز میشود و قدیمیتر دور انداخته میشود. به استناد به Apache CouchDB documentation, 2025، LWW به صورت پیشفرض در اکثر پایگاههای داده مسندگرا استفاده میشود. نشانگر زمان تنها معیار انتخاب است که الگوریتم را تعیینگرایانه و قابل پیشبینی میسازد.
نکات کلیدی
Last Write Wins (LWW) — استراتژی آخرین نوشته در حل تعارضات همگامسازی است. وقتی دو مشتری یک شی داده را تغییر میدهند، سرور هر دو نسخه را دریافت میکند و نسخهای را با نشانگر زمان (timestamp) بزرگتر انتخاب میکند. LWW استراتژی پیشفرض در بسیاری از سیستمهای توزیعشده است: Firebase Realtime Database، Apache Cassandra، Riak KV و DynamoDB در حالت آخرین نوشته.
در برنامههای موبایل، LWW به دلیل سه عامل جذاب است: سادگی پیادهسازی، تاخیر حداقل و بدون تعامل با کاربر. توسعهدهنده نیازی به نوشتن منطق ادغام پیچیده ندارد و کاربر کادرهای انتخاب نسخه را نمیبیند. اما بهای سادگی از دست رفتن پتانسیل دادهها است که همه برنامهها نمیتوانند از عهده برایند.
بطبق تحقیقات Martin Kleppmann (نویسنده «Designing Data-Intensive Applications»، O’Reilly، 2024)، LWW پراکندهترین استراتژی در سیستمهای تولیدی است که در تقریباً 70% برنامههای توزیعشده استفاده میشود که در آنها اتصاق نهایی (eventual consistency) قابل قبول است. در 23% موارد، این امر منجر به از دست رفتن قابل اندازهگیری دادههای کاربران میشود.
مکانیسم LWW بر مقایسه نشانگرهای زمان استوار است. هر نوشته داده با یک timestamp همراه است که میتواند توسط مشتری (client-side timestamp) یا سرور (server-side timestamp) تعیین شود. پس از کشف تعارض، سیستم timestamp هر دو نسخه را مقایسه میکند و نوشته با مقدار بزرگتر را قبول میکند. نسخه دوم یا دور انداخته میشود یا برای بازرسی در تاریخچه ذخیره میشود.
Client-side timestamp معیبی دارد: ساعتهای دستگاههای کاربران میتوانند ناهمگام باشند. اگر تلفن کاربر A ۵ دقیقه عقب باشد و کاربر B تغییراتی انجام دهد، نوشته A پس از تصحیح ساعت ممکن است به اشتباه جدیدتر تلقی شود. به همین دلیل، سیستمهای تولیدی بیشتر از server-side timestamp استفاده میکنند که توسط سرور در زمان دریافت داده تعیین میشود.
منطق LWW با server-side timestamp:
data class SyncDocument(
val id: String,
val data: String,
val serverTimestamp: Long
)
fun resolveLWW(
existing: SyncDocument,
incoming: SyncDocument
): SyncDocument {
return if (incoming.serverTimestamp >= existing.serverTimestamp)
incoming
else
existing
}
تابع resolveLWW دو سند را میگیرد و سندی را با timestamp بزرگتر بازمیگرداند. در صورت برابری، معمولاً سند واردشونده پیروز میشود — این تضمین میکند که دادههای جدید به دلیل اتفاق نشانگرها از دست نروند.
مزیت اصلی LWW سادگی الگوریتمی است. این استراتژی نیازی به ذخیره تاریخچه نسخهها، تحلیل تغییرات در سطح فیلدها یا حل تعارضات مرکب ندارد. سرور تعارض را در یک عملیات مقایسه تنها پردازش میکند که LWW را به سریعترین استراتژی تبدیل میکند. در Firebase Realtime Database، LWW تا 100 هزار تعارض را در ثانیه بر روی یک گره پردازش میکند.
معیب اصلی — از دست رفتن داده در تغییرات مستقل فیلدهای مختلف. اگر کاربر A نام وظیفه را تغییر دهد و کاربر B توصیف را، LWW یکی از نسخهها را کاملاً دور میاندازد، در حالی که هر دو تغییر باید ذخیره شوند. این بهویژه برای فرمها، پروفایلها و پیکربندیها که هر فیلد اهمیت دارد، حریج است.
مقایسه LWW با استراتژیهای جایگزین:
| ویژگی | LWW | Merge | CRDT |
|---|---|---|---|
| پیچیدگی | پایین | متوسط | بالا |
| از دست رفتن داده | بله | حداقل | خیر |
| عملکرد | بالا | متوسط | متوسط |
| تاریخچه نسخهها | نیاز ندارد | نیاز دارد | نیاز دارد |
| تعیینگرایانهبودن | بله | بستگی به پیادهسازی دارد | بله |
پیادهسازی LWW را در نظر بگیرید در زمینه یک برنامه موبایل لیست خرید که چندین عضو خانواده میتوانند کالاها را به صورت آفلاین اضافه کرده و علامت بزنند. هر عنصر لیست ID، نام، وضعیت و نشانگر زمان آخرین بهروزرسانی را ذخیره میکند. در زمان همگامسازی، LWW برای هر عنصر اعمال میشود.
مدل پایه عنصر لیست:
data class ShoppingItem(
val id: String,
val name: String,
val isChecked: Boolean,
val quantity: Int,
val lastModified: Long
)
fun syncWithLWW(
localItems: List<ShoppingItem>,
remoteItems: List<ShoppingItem>
): List<ShoppingItem> {
val merged = localItems.toMutableList()
remoteItems.forEach { remote ->
val index = merged.indexOfFirst { it.id == remote.id }
if (index == -1) {
merged.add(remote)
} else {
val local = merged[index]
merged[index] = if (remote.lastModified >= local.lastModified)
remote
else
local
}
}
return merged
}
تابع syncWithLWW لیستهای محلی و دور را ادغام میکند: اگر عنصر تنها در یک طرف وجود داشته باشد — اضافه میشود، اگر در هر دو طرف باشد — نسخه جدیدتر پیروز میشود. این رویکرد همگامسازی تعیینگرایانه را برای هر عنصر فردی فراهم میکند.
انتخاب بین LWW و Merge به ماهیت تغییر دادهها بستگی دارد. اگر برنامه تغییرات مستقل فیلدها را مجاز میدهد (کاربران مختلف فیلدهای مختلف یک شی را تغییر میدهند)، Merge Strategy دادهها را دقیقتر حفظ میکند. اگر تغییرات همیشه اتمی هستند (کاربر کل شی را تغییر میدهد)، LWW کاملاً مناسب است و در پیادهسازی بسیار سادهتر است.
در عمل، بسیاری از سیستمها از رویکرد ترکیبی استفاده میکنند: LWW برای متاداده و فیلدهای سطح بالا، Merge برای دادههای ساختاریافته. Firebase Firestore به عنوان مثال از LWW برای اکثر عملیات استفاده میکند، اما از تراکنشها با قفل خوشبینانه برای بهروزرسانیهای اتمی پشتیبانی میکند زمانی که توسعهدهنده صریحاً مشخص کند که فیلد نباید در زمان تعارض از دست برود.
بطبق نظرسنجی توسعهدهندگان سیستمهای توزیعشده (Stack Overflow Survey, 2025)، 54% برای MVP و پروتوتیپها LWW را انتخاب میکنند و در مرحله مقیاس به Merge یا CRDT میروند. معیار کلیدی تعداد تعارضات است: اگر کمتر از 1% نشستها منجر به تعارض شود، LWW کاملاً کافی است. اگر تعارضات بیش از 5% نشستها را تحت تأثیر قرار دهد، ارزش دارد در Merge یا CRDT سرمایهگذاری کنید.
سؤالات متداول
Last Write Wins (LWW) — استراتژی حل تعارض است که در آن از دو نسخه مترقازب، نوشته با آخرین نشانگر زمان انتخاب میشود. این سادهترین مکانیسم همگرایی است که در Firebase، Cassandra و DynamoDB استفاده میشود.
LWW استفاده میشود در Firebase Realtime Database، Apache Cassandra، Riak KV، Amazon DynamoDB (حالت آخرین نوشته) و CouchDB برای فیلدهای سطح بالا. اکثر پایگاههای داده NoSQL مسندگرا به طور پیشفرض LWW را اعمال میکنند.
بله، از دست رفتن داده ممکن است. اگر دو کاربر فیلدهای مختلف یک شی را تغییر دهند، LWW نسخه کهنه را به کلی همراه با تمامی تغییراتش دور میاندازد. برای فیلدهای مستقل، Merge Strategy یا CRDT ترجیح داده میشود.
برای کاهش از دست رفتگیها از server-side timestamp استفاده کنید، تاریخچه نسخهها را برای بازرسی ذخیره کنید و LWW را تنها برای دادههایی اعمال کنید که نسخه آخر بهطور عینی درست است. برای فیلدهای ساختاریافته، Merge Strategy را در سطح فیلد در نظر بگیرید.
تأثیر حداقل است. LWW تنها مقایسه دو مقدار عددی را طلب میکند (O(1))، که آن را به سریعترین استراتژی تبدیل میکند. Firebase Realtime Database تا 100 هزار تعارض را در ثانیه بر روی یک گره بدون کاهش قابل توجه عملکرد پردازش میکند.
نتیجهگیری
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.