मैसकल, रेडिस और मोंगो सभी बहुत लोकप्रिय स्टोर हैं, और प्रत्येक के अपने फायदे हैं। व्यावहारिक अनुप्रयोगों में, एक ही समय में कई स्टोर का उपयोग करना आम बात है और कई स्टोरों में डेटा स्थिरता सुनिश्चित करना एक आवश्यकता बन जाती है।
यह लेख कई स्टोर इंजन, मैसकल, रेडिस और मोंगो में वितरित लेनदेन को लागू करने का एक उदाहरण देता है। यह उदाहरण डिस्ट्रिब्यूटेड ट्रांजैक्शन फ्रेमवर्क https://github.com/dtm-labs/dtm पर आधारित है और उम्मीद है कि यह माइक्रोसर्विसेज में डेटा स्थिरता में आपकी समस्याओं को हल करने में मदद करेगा।
वितरित लेनदेन बनाने के लिए लचीले ढंग से कई स्टोरेज इंजनों को संयोजित करने की क्षमता सबसे पहले DTM द्वारा प्रस्तावित की गई है, और किसी अन्य वितरित लेनदेन ढांचे ने इस तरह की क्षमता को नहीं बताया है।
समस्या परिदृश्य
आइए पहले समस्या परिदृश्य को देखें। मान लीजिए कि कोई उपयोगकर्ता अब किसी प्रचार में भाग लेता है:उसके पास शेष राशि है, फ़ोन बिल रिचार्ज करें, और प्रचार मॉल पॉइंट देगा। शेष राशि मैसकल में जमा हो जाती है, बिल रेडिस में जमा हो जाता है, मॉल पॉइंट मोंगो में जमा हो जाता है। चूंकि प्रचार समय पर सीमित है, इस बात की संभावना है कि भागीदारी विफल हो सकती है, इसलिए रोलबैक समर्थन की आवश्यकता है।
उपरोक्त समस्या परिदृश्य के लिए, आप डीटीएम के सागा लेनदेन का उपयोग कर सकते हैं, और हम नीचे विस्तार से समाधान की व्याख्या करेंगे।
डेटा तैयार करना
पहला कदम डेटा तैयार करना है। उपयोगकर्ताओं के लिए उदाहरणों के साथ शीघ्रता से आरंभ करना आसान बनाने के लिए, हमने en.dtm.pub पर प्रासंगिक डेटा तैयार किया है, जिसमें मैसकल, रेडिस और मोंगो शामिल हैं, और विशिष्ट कनेक्शन उपयोगकर्ता नाम और पासवर्ड https:// पर पाया जा सकता है। github.com/dtm-labs/dtm-examples.
<ब्लॉकक्वॉट>
यदि आप स्थानीय रूप से डेटा वातावरण तैयार करना चाहते हैं, तो आप https://github.com/dtm-labs/dtm/blob/main/helper/compose.store.yml का उपयोग Mysql, Redis, Mongo शुरू करने के लिए कर सकते हैं; और फिर इस उदाहरण के लिए डेटा तैयार करने के लिए https://github.com/dtm-labs/dtm/tree/main/sqls में स्क्रिप्ट निष्पादित करें, जहां busi.*
व्यापार डेटा और barrier.*
DTM द्वारा उपयोग की जाने वाली सहायक तालिका है
बिजनेस कोड लिखना
आइए सबसे परिचित मैसकल के बिजनेस कोड से शुरुआत करें।
<ब्लॉकक्वॉट>
निम्नलिखित कोड गोलांग में है। सी#, पीएचपी, जावा जैसी अन्य भाषाएं यहां पाई जा सकती हैं:डीटीएम एसडीके
func SagaAdjustBalance(db dtmcli.DB, uid int, amount int) error {
_, err := dtmimp.DBExec(db, "update dtm_busi.user_account set balance = balance + ? where user_id = ?" , amount, uid)
return err
}
यह कोड मुख्य रूप से डेटाबेस में उपयोगकर्ता के संतुलन का समायोजन करता है। हमारे उदाहरण में, कोड के इस भाग का उपयोग न केवल सागा के आगे के संचालन के लिए किया जाता है, बल्कि मुआवजे के संचालन के लिए भी किया जाता है, जहां मुआवजे के लिए केवल एक नकारात्मक राशि को पारित करने की आवश्यकता होती है।
रेडिस और मोंगो के लिए, व्यापार कोड को समान रूप से नियंत्रित किया जाता है, बस इसी शेष राशि को बढ़ाना या घटाना।
नपुंसकता कैसे सुनिश्चित करें
सागा लेन-देन पैटर्न के लिए, जब हमारे पास उप-लेनदेन सेवा में अस्थायी विफलता होती है, तो विफल संचालन का पुन:प्रयास किया जाएगा। यह विफलता उप-लेनदेन करने से पहले या बाद में हो सकती है, इसलिए उप-लेनदेन संचालन को निष्क्रिय होना चाहिए।
DTM हेल्पर टेबल और हेल्पर फंक्शन प्रदान करता है ताकि उपयोगकर्ताओं को शीघ्रता से निष्क्रियता प्राप्त करने में मदद मिल सके। मैसकल के लिए, यह एक सहायक तालिका बनाएगा barrier
व्यापार डेटाबेस में, जब उपयोगकर्ता शेष राशि को समायोजित करने के लिए लेनदेन शुरू करता है, तो यह पहले Gid
सम्मिलित करेगा barrier
. में टेबल। यदि कोई डुप्लिकेट पंक्ति है, तो सम्मिलन विफल हो जाएगा, और फिर संतुलन को सुनिश्चित करने के लिए संतुलन समायोजन को छोड़ दें। हेल्पर फ़ंक्शन का उपयोग करने वाला कोड इस प्रकार है:
app.POST(BusiAPI+"/SagaBTransIn", dtmutil.WrapHandler2(func(c *gin.Context) interface{} {
return MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error {
return SagaAdjustBalance(tx, TransInUID, reqFrom(c).Amount, reqFrom(c).TransInResult)
})
}))
मोंगो मैसकल की तरह ही निष्क्रियता को संभालता है, इसलिए मैं फिर से विस्तार में नहीं जाऊंगा।
रेडिस मुख्य रूप से लेन-देन के सिद्धांत में अंतर के कारण, मैसकल की तुलना में अलग तरह से निष्क्रियता को संभालता है। रेडिस लेनदेन मुख्य रूप से लुआ के परमाणु निष्पादन द्वारा सुनिश्चित किया जाता है। डीटीएम हेल्पर फ़ंक्शन लुआ स्क्रिप्ट के माध्यम से शेष राशि को समायोजित करेगा। शेष राशि को समायोजित करने से पहले, यह Gid
को क्वेरी करेगा रेडिस में। अगर Gid
मौजूद है, यह संतुलन समायोजन को छोड़ देगा; यदि नहीं, तो यह Gid
. रिकॉर्ड करेगा और संतुलन समायोजन करें। हेल्पर फंक्शन के लिए प्रयुक्त कोड इस प्रकार है:
app.POST(BusiAPI+"/SagaRedisTransOut", dtmutil.WrapHandler2(func(c *gin.Context) interface{} {
return MustBarrierFromGin(c).RedisCheckAdjustAmount(RedisGet(), GetRedisAccountKey(TransOutUID), -reqFrom(c).Amount, 7*86400)
}))
मुआवजा कैसे करें
सागा के लिए, हमें मुआवजे के संचालन से निपटने की भी आवश्यकता है, लेकिन मुआवजा केवल एक रिवर्स समायोजन नहीं है, और ऐसे कई नुकसान हैं जिनके बारे में पता होना चाहिए।
एक ओर, मुआवजे को ध्यान में रखने की जरूरत है, क्योंकि पिछले उपखंड में वर्णित विफलता और पुनर्प्रयास भी मुआवजे में मौजूद हैं। दूसरी ओर, मुआवजे को भी "शून्य मुआवजे" को ध्यान में रखना होगा, क्योंकि सागा का आगे का संचालन विफल हो सकता है, जो डेटा समायोजन से पहले या बाद में हो सकता है। विफलताओं के लिए जहां समायोजन किया गया है, हमें रिवर्स समायोजन करने की आवश्यकता है; लेकिन विफलताओं के लिए जहां समायोजन नहीं किया गया है, हमें रिवर्स ऑपरेशन को छोड़ना होगा।
डीटीएम द्वारा प्रदान की गई सहायक तालिका और सहायक कार्यों में, एक तरफ, यह निर्धारित करेगा कि क्या मुआवजा फॉरवर्ड ऑपरेशन द्वारा डाले गए जीआईडी के आधार पर एक शून्य मुआवजा है, और दूसरी तरफ, यह फिर से जीआईडी + 'क्षतिपूर्ति' डालेगा। यह निर्धारित करने के लिए कि मुआवजा एक डुप्लिकेट ऑपरेशन है या नहीं। यदि कोई सामान्य मुआवजा ऑपरेशन होता है, तो यह व्यवसाय पर डेटा समायोजन निष्पादित करेगा; यदि कोई शून्य मुआवजा या डुप्लिकेट मुआवजा है, तो यह व्यवसाय पर समायोजन को छोड़ देगा।
मैसकल कोड इस प्रकार है।
app.POST(BusiAPI+"/SagaBTransInCom", dtmutil.WrapHandler2(func(c *gin.Context) interface{} {
return MustBarrierFromGin(c).Call(txGet(), func(tx *sql.Tx) error {
return SagaAdjustBalance(tx, TransInUID, -reqFrom(c).Amount, "")
})
}))
रेडिस का कोड इस प्रकार है।
app.POST(BusiAPI+"/SagaRedisTransOutCom", dtmutil.WrapHandler2(func(c *gin.Context) interface{} {
return MustBarrierFromGin(c).RedisCheckAdjustAmount(RedisGet(), GetRedisAccountKey(TransOutUID), reqFrom(c).Amount, 7*86400)
}))
मुआवजा सेवा कोड लगभग आगे के संचालन के पिछले कोड के समान है, सिवाय इसके कि राशि को -1 से गुणा किया जाता है। डीटीएम हेल्पर फ़ंक्शन स्वचालित रूप से निष्क्रियता और शून्य मुआवजे को ठीक से संभालता है।
अन्य अपवाद
आगे के संचालन और मुआवजे के संचालन को लिखते समय, वास्तव में एक और अपवाद होता है जिसे "निलंबन" कहा जाता है। एक वैश्विक लेन-देन समयबाह्य होने पर वापस रोल हो जाएगा या पुन:प्रयास कॉन्फ़िगर की गई सीमा तक पहुंच जाएगा। सामान्य स्थिति यह है कि फॉरवर्ड ऑपरेशन मुआवजे से पहले किया जाता है, लेकिन प्रक्रिया के निलंबन के मामले में फॉरवर्ड ऑपरेशन से पहले मुआवजा किया जा सकता है। इसलिए फॉरवर्ड ऑपरेशन को यह निर्धारित करने की भी आवश्यकता है कि क्या मुआवजा निष्पादित किया गया है, और यदि यह है, तो डेटा समायोजन को भी छोड़ दिया जाना चाहिए।
DTM उपयोगकर्ताओं के लिए, इन अपवादों को अच्छी तरह से और ठीक से संभाला गया है और एक उपयोगकर्ता के रूप में, आपको केवल MustBarrierFromGin(c).Call
का पालन करने की आवश्यकता है। ऊपर वर्णित कॉल और उनकी बिल्कुल भी परवाह करने की आवश्यकता नहीं है। इन अपवादों को संभालने के लिए डीटीएम के सिद्धांत का यहां विस्तार से वर्णन किया गया है:अपवाद और उप-लेनदेन बाधाएं
एक वितरित लेनदेन शुरू करना
व्यक्तिगत उप-लेनदेन सेवाओं को लिखने के बाद, कोड के निम्नलिखित कोड सागा वैश्विक लेनदेन शुरू करते हैं।
saga := dtmcli.NewSaga(dtmutil.DefaultHTTPServer, dtmcli.MustGenGid(dtmutil.DefaultHTTPServer)).
Add(busi.Busi+"/SagaBTransOut", busi.Busi+"/SagaBTransOutCom", &busi.TransReq{Amount: 50}).
Add(busi.Busi+"/SagaMongoTransIn", busi.Busi+"/SagaMongoTransInCom", &busi.TransReq{Amount: 30}).
Add(busi.Busi+"/SagaRedisTransIn", busi.Busi+"/SagaRedisTransOutIn", &busi.TransReq{Amount: 20})
err := saga.Submit()
कोड के इस भाग में, एक सागा वैश्विक लेनदेन बनाया जाता है जिसमें 3 उप-लेनदेन होते हैं।
- माइस्क्ल से 50 में से ट्रांसफर करें
- 30 में मोंगो में स्थानांतरण
- 20 में Redis में ट्रांसफर करें
लेन-देन के दौरान, यदि सभी उप-लेन-देन सफलतापूर्वक पूर्ण होते हैं, तो वैश्विक लेनदेन सफल होता है; यदि उप-लेनदेनों में से कोई एक व्यावसायिक विफलता देता है, तो वैश्विक लेनदेन वापस आ जाता है।
भागो
यदि आप उपरोक्त का पूरा उदाहरण चलाना चाहते हैं, तो चरण इस प्रकार हैं।
- डीटीएम चलाएं
git clone https://github.com/dtm-labs/dtm && cd dtm
go run main.go
- एक सफल उदाहरण चलाएँ
git clone https://github.com/dtm-labs/dtm-examples && cd dtm-examples
go run main.go http_saga_multidb
- विफल उदाहरण चलाएँ
git clone https://github.com/dtm-labs/dtm-examples && cd dtm-examples
go run main.go http_saga_multidb_rollback
आप विभिन्न अस्थायी विफलताओं, शून्य क्षतिपूर्ति स्थितियों, और विभिन्न अन्य अपवादों को अनुकरण करने के लिए उदाहरण को संशोधित कर सकते हैं जहां संपूर्ण वैश्विक लेनदेन समाप्त होने पर डेटा सुसंगत है।
सारांश
यह आलेख मैसकल, रेडिस और मोंगो में वितरित लेनदेन का एक उदाहरण देता है। यह उन समस्याओं और समाधानों का विस्तार से वर्णन करता है जिनसे निपटने की आवश्यकता है।
इस लेख के सिद्धांत सभी भंडारण इंजनों के लिए उपयुक्त हैं जो ACID लेनदेन का समर्थन करते हैं, और आप इसे अन्य इंजनों जैसे TiKV के लिए जल्दी से बढ़ा सकते हैं।
github.com/dtm-labs/dtm पर जाने के लिए आपका स्वागत है। यह माइक्रोसर्विसेज में वितरित लेनदेन को आसान बनाने के लिए एक समर्पित परियोजना है। यह कई भाषाओं का समर्थन करता है, और 2-चरण संदेश, सागा, टीसीसी, और एक्सए जैसे कई पैटर्न का समर्थन करता है।