स्पार्क में, RDD
. पर कार्य करता है s (जैसे map
यहाँ) क्रमबद्ध हैं और प्रसंस्करण के लिए निष्पादकों को भेजते हैं। इसका तात्पर्य यह है कि उन परिचालनों में निहित सभी तत्वों को क्रमबद्ध किया जाना चाहिए।
यहां रेडिस कनेक्शन क्रमबद्ध नहीं है क्योंकि यह लक्ष्य डीबी के लिए टीसीपी कनेक्शन खोलता है जो उस मशीन से बंधे होते हैं जहां इसे बनाया गया है।
समाधान स्थानीय निष्पादन संदर्भ में, निष्पादकों पर उन कनेक्शनों को बनाना है। ऐसा करने के कुछ तरीके हैं। दो जो दिमाग में आते हैं वे हैं:
rdd.mapPartitions
:आपको एक ही बार में पूरे विभाजन को संसाधित करने देता है, और इसलिए कनेक्शन बनाने की लागत को परिशोधित करता है)- सिंगलटन कनेक्शन प्रबंधक:प्रति निष्पादक एक बार कनेक्शन बनाएं
mapPartitions
यह आसान है क्योंकि इसके लिए केवल कार्यक्रम संरचना में एक छोटे से बदलाव की आवश्यकता होती है:
val perhit = perhitFile.mapPartitions{partition =>
val r = new RedisClient("192.168.1.101", 6379) // create the connection in the context of the mapPartition operation
val res = partition.map{ x =>
...
val refStr = r.hmget(...) // use r to process the local data
}
r.close // take care of resources
res
}
एक सिंगलटन कनेक्शन मैनेजर को किसी ऑब्जेक्ट के साथ मॉडलिंग किया जा सकता है जिसमें कनेक्शन के लिए आलसी संदर्भ होता है (नोट:एक परिवर्तनीय रेफरी भी काम करेगा)।
object RedisConnection extends Serializable {
lazy val conn: RedisClient = new RedisClient("192.168.1.101", 6379)
}
इस ऑब्जेक्ट का उपयोग प्रति कार्यकर्ता JVM में 1 कनेक्शन को तुरंत करने के लिए किया जा सकता है और इसे Serializable
के रूप में उपयोग किया जाता है एक ऑपरेशन क्लोजर में ऑब्जेक्ट।
val perhit = perhitFile.map{x =>
val param = f(x)
val refStr = RedisConnection.conn.hmget(...) // use RedisConnection to get a connection to the local data
}
}
सिंगलटन ऑब्जेक्ट का उपयोग करने का लाभ कम ओवरहेड है क्योंकि कनेक्शन केवल एक बार JVM द्वारा बनाए जाते हैं (जैसा कि 1 प्रति RDD विभाजन के विपरीत)
इसके कुछ नुकसान भी हैं:
- कनेक्शन की सफाई मुश्किल है (शटडाउन हुक/टाइमर)
- साझा संसाधनों की थ्रेड-सुरक्षा सुनिश्चित करनी चाहिए
(*) कोड चित्रण उद्देश्यों के लिए प्रदान किया गया। संकलित या परीक्षण नहीं किया गया।