2012-07-02 5 views
7

मैं एक बहु लेनदेन में रेडिस कमांड का एक जटिल सेट encapsulating हूँ, लेकिन लेनदेन में तर्क Redis में पहले से ही मूल्यों पर निर्भर करता है। लेकिन सभी एक सौदे के भीतर पढ़ता यहाँ एक उदाहरण है कि समस्या को दर्शाता है है nilरुबी में एक बहु ब्लॉक के अंदर रेडिस से मैं कैसे पढ़ सकता हूं?

लौटने के लिए लग रहे हैं:

[Dev]> $redis.set("foo", "bar") 
=> "OK" 
[Dev]> $redis.multi{ $redis.set("foo", "baz") if $redis.get("foo") == "bar" } 
=> ["bar"] 
[Dev]> $redis.get("foo") 
=> "bar" 

जाहिर है मैं पिछले वापसी मान 'baz' होना चाहता हूँ - मैं यह कैसे प्राप्त कर सकते हैं?

+0

मुझे डर है कि आप ऐसा नहीं कर सकते हैं। –

उत्तर

1

सर्जीओ अपनी टिप्पणी में कहता है, आप वैकल्पिक रूप से रेडिस में MULTI ब्लॉक निष्पादित नहीं कर सकते हैं। documentation on transactions देखें:

या तो सभी आदेश या कोई भी संसाधित नहीं होता है।

हालांकि, आप WATCH का उपयोग जांच और सेट (छद्म कोड) का उपयोग कर आशावादी ताला लागू करने के लिए कर सकते हैं:

SET foo bar 
WATCH foo 
$foo = GET foo 
MULTI 
if $foo == 'bar' 
    SET foo baz 
EXEC 
GET foo 

WATCH का उपयोग करना, लेन-देन ही निष्पादित किया जाएगा यदि देखा कुंजी (रों) नहीं बदला गया है। यदि घड़ी कुंजी बदल दी गई है, तो EXEC विफल हो जाएगा, और आप फिर कोशिश कर सकते हैं।

एक और संभावना स्क्रिप्टिंग कार्यक्षमता का उपयोग कर रही है, लेकिन यह केवल 2.6 रिलीज उम्मीदवार में उपलब्ध है।

16

आप नहीं कर सकते, क्योंकि सभी आदेश (प्राप्त करने सहित) वास्तव में निष्पादन समय पर निष्पादित होते हैं। इस स्थिति में, प्राप्त आदेश केवल भविष्य की वस्तु देता है, वास्तविक मूल्य नहीं।

ऐसे लेनदेन को लागू करने के दो तरीके हैं।

एक घड़ी खंड

का उपयोग करते हुए घड़ी खंड समवर्ती अद्यतन के खिलाफ की रक्षा करने के लिए प्रयोग किया जाता है। यदि वैरिएबल का मान घड़ी और बहु ​​खंड के बीच अद्यतन किया गया है, तो बहु ब्लॉक में कमांड लागू नहीं होते हैं। यह किसी अन्य समय लेनदेन का प्रयास करने के लिए ग्राहक पर निर्भर है।

loop do 
    $redis.watch "foo" 
    val = $redis.get("foo") 
    if val == "bar" then 
     res = $redis.multi do |r| 
      r.set("foo", "baz") 
     end 
     break if res 
    else 
     $redis.unwatch "foo" 
     break 
    end 
end 

यहाँ स्क्रिप्ट थोड़ा जटिल है क्योंकि ब्लॉक की सामग्री को खाली हो सकता है है, इसलिए वहाँ कोई आसान तरीका जानने के लिए कि लेन-देन रद्द कर दिया गया है, या क्या यह सब पर जगह नहीं लिया। यह आमतौर पर आसान होता है जब मल्टी ब्लॉक सभी मामलों में परिणाम देता है सिवाय इसके कि लेनदेन रद्द कर दिया गया है।

लुआ सर्वर-साइड स्क्रिप्टिंग

का उपयोग Redis 2.6 या बेहतर के साथ, लुआ स्क्रिप्ट सर्वर पर क्रियान्वित किया जा सकता। पूरी लिपि का निष्पादन परमाणु है। यह आसानी से रूबी में लागू किया जा सकता:

cmd = <<EOF 
    if redis.call('get',KEYS[1]) == ARGV[1] then 
     redis.call('set',KEYS[1],ARGV[2]) 
    end 
EOF 
$redis.eval cmd, 1, "foo", "bar", "baz" 

यह आमतौर पर बहुत वॉच खंड का उपयोग करने से आसान है।

संबंधित मुद्दे