मर्ज रणनीति एक डेटा विलय रणनीति है जिसमें विभिन्न संस्करणों से विरोधाभासी परिवर्तनों को एक संस्करण को दूसरे से बदलने के बजाय एक सुसंगत स्थिति में जोड़ दिया जाता है। Last Write Wins के विपरीत, मर्ज डेटा हानि को कम करते हुए सभी शाखाओं से परिवर्तनों को संरक्षित करने का प्रयास करता है। Apache CouchDB दस्तावेज़ीकरण, 2025 के अनुसार, त्रि-पक्षीय मर्ज (three-way merge) दस्तावेज़-उन्मुख डेटाबेस में विरोध समाधान का मानक तंत्र है। त्रि-पक्षीय मर्ज यह निर्धारित करने के लिए एक सामान्य आधार संस्करण का उपयोग करता है कि प्रत्येक क्लाइंट द्वारा कौन से फ़ील्ड बदले गए।
मुख्य बिंदु
मर्ज रणनीति एल्गोरिदम का एक सेट है जो उनमें से एक को चुनने के बजाय विरोधाभासी डेटा संस्करणों को जोड़ता है। मोबाइल एप्लिकेशन में, मर्ज का उपयोग तब किया जाता है जब दो क्लाइंट स्वतंत्र रूप से एक ही ऑब्जेक्ट के विभिन्न फ़ील्ड या गुणों को संपादित करते हैं। पुराने संस्करण को पूरी तरह से खारिज करने के बजाय (जैसा कि LWW में), सिस्टम व्यक्तिगत फ़ील्ड स्तर पर अंतर का विश्लेषण करता है और दोनों संस्करणों से परिवर्तनों वाला एक परिणामी ऑब्जेक्ट उत्पन्न करता है।
मुख्य अंतर मर्ज और LWW के बीच यह है कि यह प्रत्येक उपयोगकर्ता के परिवर्तनों को संरक्षित करता है बशर्ते वे एक दूसरे के विरोधाभासी न हों। यदि उपयोगकर्ता A ने कार्य का नाम बदला और उपयोगकर्ता B ने विवरण बदला, तो मर्ज दोनों परिवर्तनों को संरक्षित करता है। यदि दोनों ने एक ही फ़ील्ड बदला — एक विरोध दर्ज किया जाता है जिसे हल करने की आवश्यकता होती है। यह मर्ज को उन अनुप्रयोगों के लिए बेहतर बनाता है जहाँ उपयोगकर्ता एक ही डेटा पर सहयोगात्मक रूप से काम करते हैं।
Stripe Engineering Blog (2025) की एक रिपोर्ट के अनुसार, LWW के बजाय मर्ज रणनीति लागू करने से उनके मोबाइल प्रोजेक्ट प्रबंधन एप्लिकेशन में डेटा हानि के बारे में उपयोगकर्ता शिकायतों की संख्या में 76% की कमी आई। हालाँकि, विरोध प्रसंस्करण समय में 15–30 ms की वृद्धि हुई, जिसे डेटा अखंडता के लिए स्वीकार्य मूल्य माना जाता है।
त्रि-पक्षीय मर्ज (three-way merge) मर्ज रणनीति का सबसे सामान्य कार्यान्वयन है। तंत्र तीन डेटा संस्करणों के साथ काम करता है: आधार (विचलन से पहले की स्थिति), स्थानीय (वर्तमान क्लाइंट का संस्करण) और दूरस्थ (सर्वर संस्करण)। सिस्टम यह निर्धारित करने के लिए स्थानीय और दूरस्थ संस्करणों के प्रत्येक फ़ील्ड की आधार से तुलना करता है कि किस पक्ष ने कौन से फ़ील्ड बदले।
निर्णय तर्क सरल है: यदि केवल एक क्लाइंट ने फ़ील्ड बदला (आधार के सापेक्ष), तो उसका परिवर्तन स्वचालित रूप से स्वीकार किया जाता है। यदि दोनों क्लाइंट ने एक ही फ़ील्ड बदला — एक विरोध दर्ज किया जाता है जिसे स्वचालित रूप से (प्राथमिकता द्वारा) हल किया जा सकता है या उपयोगकर्ता को सौंपा जा सकता है। यदि किसी भी क्लाइंट ने फ़ील्ड नहीं बदला — आधार मान बना रहता है। यह दृष्टिकोण गारंटी देता है कि स्वतंत्र परिवर्तन न तो खोए जाते हैं और न ही विरोधाभासी होते हैं।
फ़ील्ड शब्दकोश स्तर पर त्रि-पक्षीय मर्ज एल्गोरिदम:
fun threeWayMerge(
base: Map<String, Any?>,
local: Map<String, Any?>,
remote: Map<String, Any?>
): Map<String, Any?> {
val result = base.toMutableMap()
val allKeys = base.keys + local.keys + remote.keys
allKeys.forEach { key ->
val baseVal = base[key]
val localVal = local[key]
val remoteVal = remote[key]
result[key] = when {
localVal == baseVal -> remoteVal
remoteVal == baseVal -> localVal
localVal == remoteVal -> localVal
else -> // real conflict
resolveConflict(key, localVal, remoteVal)
}
}
return result
}
threeWayMerge फ़ंक्शन तीनों संस्करणों से सभी कुंजियों को क्रमिक रूप से संसाधित करता है। यदि स्थानीय मान आधार से मेल खाता है — दूरस्थ परिवर्तन स्वीकार किया जाता है। यदि दूरस्थ आधार से मेल खाता है — स्थानीय परिवर्तन स्वीकार किया जाता है। यदि दोनों आधार से भिन्न हैं लेकिन एक दूसरे के बराबर हैं — कोई भी स्वीकार किया जाता है। एक वास्तविक विरोध केवल तब दर्ज किया जाता है जब दोनों पक्षों में अलग-अलग परिवर्तन हों।
स्वचालित समाधान तब लागू किया जाता है जब परिवर्तन ओवरलैप नहीं होते या जब सिस्टम नियमों के आधार पर सही मान निर्धारित कर सकता है। उदाहरण के लिए, संख्यात्मक फ़ील्ड के लिए अधिकतम मान चुना जा सकता है, टेक्स्ट फ़ील्ड के लिए — संयोजन या नया संस्करण। CouchDB JSON दस्तावेज़ फ़ील्ड के लिए स्वचालित मर्ज का उपयोग करता है, और सरणियों के लिए — डुप्लिकेट हटाने के साथ संयोजन।
मैन्युअल समाधान आवश्यक है जब दो उपयोगकर्ताओं ने एक ही फ़ील्ड को अलग-अलग बदला हो। इस मामले में, एप्लिकेशन तीन विकल्पों के साथ एक संवाद दिखाता है: “स्थानीय संस्करण स्वीकार करें”, “दूरस्थ संस्करण स्वीकार करें” या “मैन्युअल रूप से मर्ज करें”। CMU (कार्नेगी मेलन विश्वविद्यालय, 2024) के शोध के अनुसार, मैन्युअल समाधान उपयोगकर्ता संतुष्टि को 40% तक कम कर देता है, इसलिए स्वचालित मर्ज को अधिकतम किया जाना चाहिए।
विभिन्न फ़ील्ड प्रकारों के लिए समाधान रणनीतियाँ:
| फ़ील्ड प्रकार | स्वचालित रणनीति | मैन्युअल विकल्प |
|---|---|---|
| संख्या (काउंटर) | अधिकतम लें | दोनों मान दिखाएँ |
| टेक्स्ट (स्ट्रिंग) | समय के अनुसार चुनें | हाइलाइटेड संपादक |
| बूलियन | भूमिकाओं द्वारा प्राथमिकता | तीन चयन विकल्प |
| सरणी (सूची) | डिडुप्लीकेशन के साथ मर्ज | तत्व-वार चयन |
| नेस्टेड ऑब्जेक्ट | पुनरावर्ती मर्ज | अंतर दिखाएँ |
आइए विचार करें REST API के माध्यम से सिंक्रोनाइज़ेशन वाले मोबाइल एप्लिकेशन में उपयोगकर्ता प्रोफ़ाइल के लिए मर्ज रणनीति का कार्यान्वयन। प्रोफ़ाइल में नाम, ईमेल, अवतार और सूचना सेटिंग्स शामिल हैं। प्रत्येक फ़ील्ड को विभिन्न उपयोगकर्ता उपकरणों पर स्वतंत्र रूप से बदला जा सकता है।
फ़ील्ड-स्तरीय संस्करणीकरण के साथ प्रोफ़ाइल डेटा वर्ग:
data class UserProfile(
val displayName: String,
val email: String,
val avatarUrl: String,
val notificationsEnabled: Boolean
)
data class ProfileSnapshot(
val profile: UserProfile,
val version: Int
)
fun mergeProfiles(
base: UserProfile,
local: UserProfile,
remote: UserProfile
): UserProfile {
return UserProfile(
displayName = if (local.displayName != base.displayName)
local.displayName else remote.displayName,
email = if (local.email != base.email)
local.email else remote.email,
avatarUrl = if (remote.avatarUrl != base.avatarUrl)
remote.avatarUrl else local.avatarUrl,
notificationsEnabled = if (local.notificationsEnabled != base.notificationsEnabled)
local.notificationsEnabled
else remote.notificationsEnabled
)
}
mergeProfiles फ़ंक्शन प्रोफ़ाइल के प्रत्येक फ़ील्ड को स्वतंत्र रूप से संसाधित करता है, उस संस्करण का चयन करता है जो आधार से भिन्न है। विरोध की स्थिति में (दोनों आधार से भिन्न), प्राथमिकता एप्लिकेशन नियमों द्वारा निर्धारित की जाती है। उदाहरण में, avatarUrl के लिए दूरस्थ संस्करण को प्राथमिकता दी जाती है, शेष फ़ील्ड के लिए — स्थानीय को।
CouchDB और PouchDB अंतर्निहित मर्ज रणनीति समर्थन वाले सबसे प्रसिद्ध डेटाबेस हैं। दस्तावेज़ प्रतिकृति के दौरान, CouchDB दस्तावेज़ स्तर पर विरोध का पता लगाने के साथ बहु-थ्रेडेड प्रतिकृति का उपयोग करता है। आधार संस्करण संशोधन इतिहास में संग्रहीत किया जाता है, और विरोध की स्थिति में, सिस्टम सभी विरोधाभासी शाखाओं को संरक्षित करता है और एप्लिकेशन को मर्ज तंत्र के माध्यम से उन्हें हल करने के लिए API प्रदान करता है।
Firebase Firestore में, मर्ज आशावादी लॉकिंग के साथ लेन-देन के माध्यम से कार्यान्वित किया जाता है। डेवलपर निर्दिष्ट कर सकता है कि कुछ फ़ील्ड को FieldValue.serverTimestamp() और FieldValue.arrayUnion() का उपयोग करके परमाणु रूप से अपडेट किया जाना चाहिए। हालाँकि, Firestore पूर्ण त्रि-पक्षीय मर्ज का समर्थन नहीं करता — विरोध होने पर, लेन-देन नए डेटा के साथ पुनः प्रयास किया जाता है, जो वास्तविक मर्ज के बजाय पुनः प्रयास के बराबर है।
Kotlin Multiplatform और React Native पर मोबाइल एप्लिकेशन के लिए, मर्ज रणनीति क्लाइंट पक्ष पर कार्यान्वित की जाती है। स्थानीय डेटाबेस (SQLite, Realm) प्रत्येक दस्तावेज़ का संस्करण संग्रहीत करता है, और सिंक्रोनाइज़ेशन के दौरान, क्लाइंट सर्वर संस्करण लोड करता है और परिणाम भेजने से पहले स्थानीय रूप से मर्ज करता है। यह दृष्टिकोण लंबे समय तक ऑफ़लाइन संचालन के दौरान भी डेटा अखंडता सुनिश्चित करता है जब अधिक विरोध जमा होते हैं।
अक्सर पूछे जाने वाले प्रश्न
मर्ज रणनीति विरोध समाधान का एक दृष्टिकोण है जिसमें विभिन्न संस्करणों के परिवर्तन एक ही स्थिति में जोड़ दिए जाते हैं। LWW के विपरीत, मर्ज दोनों शाखाओं से परिवर्तनों को संरक्षित करता है यदि वे फ़ील्ड स्तर पर एक दूसरे के विरोधाभासी न हों।
त्रि-पक्षीय मर्ज यह निर्धारित करने के लिए आधार संस्करण (विचलन से पहले की स्थिति) का उपयोग करता है कि प्रत्येक क्लाइंट ने कौन से फ़ील्ड बदले। द्वि-पक्षीय मर्ज मूल स्थिति को जाने बिना केवल दो संस्करणों की तुलना करता है, जो अक्सर गलत विरोध की ओर ले जाता है।
CouchDB और PouchDB में अंतर्निहित त्रि-पक्षीय मर्ज समर्थन है। Firebase Firestore को लेन-देन स्तर पर कार्यान्वयन की आवश्यकता है। MongoDB और Realm आशावादी लॉकिंग तंत्र प्रदान करते हैं लेकिन पूर्ण स्वचालित मर्ज नहीं।
मर्ज उपयुक्त नहीं है उस डेटा के लिए जहाँ प्रसंस्करण गति महत्वपूर्ण है (प्रति सेकंड 1000 से अधिक विरोध), स्ट्रीमिंग डेटा (लॉग, घटनाएँ) और उन मामलों के लिए जहाँ परिवर्तन मौलिक रूप से असंगत हैं (विभिन्न स्कीमा संस्करण)। इन मामलों में, LWW या CRDT अधिक कुशल होंगे।
कार्यान्वयन में तीन चरण शामिल हैं: सर्वर से डेटा लोड करते समय आधार संस्करण संग्रहीत करना, सहेजते समय फ़ील्ड स्तर पर परिवर्तनों का पता लगाना और सिंक्रोनाइज़ेशन के दौरान मर्ज एल्गोरिदम को कॉल करना। सरलता के लिए, JSON Patch या CRDT लाइब्रेरी का उपयोग करें।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें