redis 1.0.7 → 2.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +8 -0
- data/lib/redis.rb +467 -3
- data/lib/redis/client.rb +145 -464
- data/lib/redis/distributed.rb +388 -67
- data/lib/redis/pipeline.rb +5 -11
- data/lib/redis/subscribe.rb +83 -10
- metadata +11 -9
- data/lib/redis/dist_redis.rb +0 -16
data/lib/redis/distributed.rb
CHANGED
@@ -1,115 +1,436 @@
|
|
1
|
-
require
|
1
|
+
require "redis/hash_ring"
|
2
2
|
|
3
3
|
class Redis
|
4
4
|
class Distributed
|
5
|
+
|
6
|
+
class CannotDistribute < RuntimeError
|
7
|
+
def initialize(command)
|
8
|
+
@command = command
|
9
|
+
end
|
10
|
+
|
11
|
+
def message
|
12
|
+
"#{@command.to_s.upcase} cannot be used in Redis::Distributed because the keys involved need to be on the same server or because we cannot guarantee that the operation will be atomic."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
5
16
|
attr_reader :ring
|
6
|
-
def initialize(opts={})
|
7
|
-
hosts = []
|
8
17
|
|
9
|
-
|
10
|
-
|
18
|
+
def initialize(urls, options = {})
|
19
|
+
@default_options = options
|
20
|
+
@ring = HashRing.new urls.map { |url| Redis.connect(options.merge(:url => url)) }
|
21
|
+
end
|
11
22
|
|
12
|
-
|
23
|
+
def node_for(key)
|
24
|
+
@ring.get_node(key.to_s)
|
25
|
+
end
|
13
26
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
27
|
+
def nodes
|
28
|
+
@ring.nodes
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_node(url)
|
32
|
+
@ring.add_node Redis.connect(@default_options.merge(:url => url))
|
33
|
+
end
|
34
|
+
|
35
|
+
def quit
|
36
|
+
on_each_node :quit
|
37
|
+
rescue Errno::ECONNRESET
|
38
|
+
end
|
39
|
+
|
40
|
+
def select(db)
|
41
|
+
on_each_node :select, db
|
42
|
+
end
|
43
|
+
|
44
|
+
def ping
|
45
|
+
on_each_node :ping
|
46
|
+
end
|
47
|
+
|
48
|
+
def quit
|
49
|
+
on_each_node :quit
|
50
|
+
end
|
51
|
+
|
52
|
+
def flushall
|
53
|
+
on_each_node :flushall
|
54
|
+
end
|
55
|
+
|
56
|
+
def exists(key)
|
57
|
+
node_for(key).exists(key)
|
58
|
+
end
|
59
|
+
|
60
|
+
def del(*keys)
|
61
|
+
on_each_node(:del, *keys)
|
62
|
+
end
|
63
|
+
|
64
|
+
def type(key)
|
65
|
+
node_for(key).type(key)
|
66
|
+
end
|
67
|
+
|
68
|
+
def keys(glob = "*")
|
69
|
+
on_each_node(:keys, glob).flatten
|
70
|
+
end
|
71
|
+
|
72
|
+
def randomkey
|
73
|
+
raise CannotDistribute, :randomkey
|
74
|
+
end
|
75
|
+
|
76
|
+
def rename(old_name, new_name)
|
77
|
+
raise CannotDistribute, :rename
|
78
|
+
end
|
79
|
+
|
80
|
+
def renamenx(old_name, new_name)
|
81
|
+
raise CannotDistribute, :renamenx
|
82
|
+
end
|
83
|
+
|
84
|
+
def dbsize
|
85
|
+
on_each_node :dbsize
|
86
|
+
end
|
87
|
+
|
88
|
+
def expire(key, seconds)
|
89
|
+
node_for(key).expire(key, seconds)
|
90
|
+
end
|
91
|
+
|
92
|
+
def expireat(key, unix_time)
|
93
|
+
node_for(key).expireat(key, unix_time)
|
94
|
+
end
|
95
|
+
|
96
|
+
def ttl(key)
|
97
|
+
node_for(key).ttl(key)
|
98
|
+
end
|
99
|
+
|
100
|
+
def move(key, db)
|
101
|
+
node_for(key).move(key, db)
|
102
|
+
end
|
103
|
+
|
104
|
+
def flushdb
|
105
|
+
on_each_node :flushdb
|
106
|
+
end
|
107
|
+
|
108
|
+
def set(key, value)
|
109
|
+
node_for(key).set(key, value)
|
110
|
+
end
|
111
|
+
|
112
|
+
def setex(key, ttl, value)
|
113
|
+
node_for(key).setex(key, ttl, value)
|
114
|
+
end
|
115
|
+
|
116
|
+
def get(key)
|
117
|
+
node_for(key).get(key)
|
118
|
+
end
|
119
|
+
|
120
|
+
def getset(key, value)
|
121
|
+
node_for(key).getset(key, value)
|
122
|
+
end
|
123
|
+
|
124
|
+
def [](key)
|
125
|
+
get(key)
|
126
|
+
end
|
127
|
+
|
128
|
+
def []=(key,value)
|
129
|
+
set(key, value)
|
130
|
+
end
|
131
|
+
|
132
|
+
def mget(*keys)
|
133
|
+
raise CannotDistribute, :mget
|
134
|
+
end
|
135
|
+
|
136
|
+
def mapped_mget(*keys)
|
137
|
+
raise CannotDistribute, :mapped_mget
|
138
|
+
end
|
139
|
+
|
140
|
+
def setnx(key, value)
|
141
|
+
node_for(key).setnx(key, value)
|
142
|
+
end
|
143
|
+
|
144
|
+
def mset(*args)
|
145
|
+
raise CannotDistribute, :mset
|
146
|
+
end
|
147
|
+
|
148
|
+
def mapped_mset(hash)
|
149
|
+
mset(*hash.to_a.flatten)
|
150
|
+
end
|
151
|
+
|
152
|
+
def msetnx(*args)
|
153
|
+
raise CannotDistribute, :msetnx
|
154
|
+
end
|
155
|
+
|
156
|
+
def mapped_msetnx(hash)
|
157
|
+
raise CannotDistribute, :mapped_msetnx
|
158
|
+
end
|
159
|
+
|
160
|
+
def incr(key)
|
161
|
+
node_for(key).incr(key)
|
162
|
+
end
|
163
|
+
|
164
|
+
def incrby(key, increment)
|
165
|
+
node_for(key).incrby(key, increment)
|
166
|
+
end
|
167
|
+
|
168
|
+
def decr(key)
|
169
|
+
node_for(key).decr(key)
|
170
|
+
end
|
171
|
+
|
172
|
+
def decrby(key, decrement)
|
173
|
+
node_for(key).decrby(key, decrement)
|
174
|
+
end
|
175
|
+
|
176
|
+
def rpush(key, value)
|
177
|
+
node_for(key).rpush(key, value)
|
178
|
+
end
|
179
|
+
|
180
|
+
def lpush(key, value)
|
181
|
+
node_for(key).lpush(key, value)
|
182
|
+
end
|
183
|
+
|
184
|
+
def llen(key)
|
185
|
+
node_for(key).llen(key)
|
186
|
+
end
|
187
|
+
|
188
|
+
def lrange(key, start, stop)
|
189
|
+
node_for(key).lrange(key, start, stop)
|
190
|
+
end
|
191
|
+
|
192
|
+
def ltrim(key, start, stop)
|
193
|
+
node_for(key).ltrim(key, start, stop)
|
194
|
+
end
|
18
195
|
|
19
|
-
|
196
|
+
def lindex(key, index)
|
197
|
+
node_for(key).lindex(key, index)
|
20
198
|
end
|
21
199
|
|
22
|
-
def
|
23
|
-
key
|
24
|
-
@ring.get_node(key)
|
200
|
+
def lset(key, index, value)
|
201
|
+
node_for(key).lset(key, index, value)
|
25
202
|
end
|
26
203
|
|
27
|
-
def
|
28
|
-
|
29
|
-
@ring.add_node Client.new(:host => server, :port => port)
|
204
|
+
def lrem(key, count, value)
|
205
|
+
node_for(key).lrem(key, count, value)
|
30
206
|
end
|
31
207
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
208
|
+
def lpop(key)
|
209
|
+
node_for(key).lpop(key)
|
210
|
+
end
|
211
|
+
|
212
|
+
def rpop(key)
|
213
|
+
node_for(key).rpop(key)
|
214
|
+
end
|
215
|
+
|
216
|
+
def rpoplpush(source, destination)
|
217
|
+
raise CannotDistribute, :rpoplpush
|
218
|
+
end
|
219
|
+
|
220
|
+
def blpop(key, timeout)
|
221
|
+
node_for(key).blpop(key, timeout)
|
222
|
+
end
|
223
|
+
|
224
|
+
def brpop(key, timeout)
|
225
|
+
node_for(key).brpop(key, timeout)
|
226
|
+
end
|
227
|
+
|
228
|
+
def sadd(key, value)
|
229
|
+
node_for(key).sadd(key, value)
|
230
|
+
end
|
231
|
+
|
232
|
+
def srem(key, value)
|
233
|
+
node_for(key).srem(key, value)
|
234
|
+
end
|
235
|
+
|
236
|
+
def spop(key)
|
237
|
+
node_for(key).spop(key)
|
238
|
+
end
|
239
|
+
|
240
|
+
def smove(source, destination, member)
|
241
|
+
raise CannotDistribute, :smove
|
242
|
+
end
|
243
|
+
|
244
|
+
def scard(key)
|
245
|
+
node_for(key).scard(key)
|
246
|
+
end
|
247
|
+
|
248
|
+
def sismember(key, member)
|
249
|
+
node_for(key).sismember(key, member)
|
250
|
+
end
|
251
|
+
|
252
|
+
def sinter(*keys)
|
253
|
+
raise CannotDistribute, :sinter
|
254
|
+
end
|
255
|
+
|
256
|
+
def sinterstore(destination, *keys)
|
257
|
+
raise CannotDistribute, :sinterstore
|
258
|
+
end
|
259
|
+
|
260
|
+
def sunion(*keys)
|
261
|
+
raise CannotDistribute, :sunion
|
262
|
+
end
|
263
|
+
|
264
|
+
def sunionstore(*keys)
|
265
|
+
raise CannotDistribute, :sunionstore
|
266
|
+
end
|
267
|
+
|
268
|
+
def sdiff(*keys)
|
269
|
+
raise CannotDistribute, :sdiff
|
270
|
+
end
|
271
|
+
|
272
|
+
def sdiffstore(*keys)
|
273
|
+
raise CannotDistribute, :sdiffstore
|
274
|
+
end
|
275
|
+
|
276
|
+
def smembers(key)
|
277
|
+
node_for(key).smembers(key)
|
278
|
+
end
|
279
|
+
|
280
|
+
def srandmember(key)
|
281
|
+
node_for(key).srandmember(key)
|
282
|
+
end
|
283
|
+
|
284
|
+
def zadd(key, score, member)
|
285
|
+
node_for(key).zadd(key, score, member)
|
286
|
+
end
|
287
|
+
|
288
|
+
def zrem(key, member)
|
289
|
+
node_for(key).zrem(key, member)
|
290
|
+
end
|
291
|
+
|
292
|
+
def zincrby(key, increment, member)
|
293
|
+
node_for(key).zincrby(key, increment, member)
|
294
|
+
end
|
295
|
+
|
296
|
+
def zrange(key, start, stop, with_scores = false)
|
297
|
+
if with_scores
|
298
|
+
node_for(key).zrange(key, start, stop, "WITHSCORES")
|
35
299
|
else
|
36
|
-
|
300
|
+
node_for(key).zrange(key, start, stop)
|
37
301
|
end
|
38
302
|
end
|
39
303
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
304
|
+
def zrevrange(key, start, stop, with_scores = false)
|
305
|
+
if with_scores
|
306
|
+
node_for(key).zrevrange(key, start, stop, "WITHSCORES")
|
307
|
+
else
|
308
|
+
node_for(key).zrevrange(key, start, stop)
|
43
309
|
end
|
44
310
|
end
|
45
311
|
|
46
|
-
def
|
47
|
-
|
312
|
+
def zrangebyscore(key, min, max)
|
313
|
+
node_for(key).zrangebyscore(key, min, max)
|
48
314
|
end
|
49
315
|
|
50
|
-
def
|
51
|
-
|
316
|
+
def zcard(key)
|
317
|
+
node_for(key).zcard(key)
|
52
318
|
end
|
53
319
|
|
54
|
-
def
|
55
|
-
|
320
|
+
def zscore(key, member)
|
321
|
+
node_for(key).zscore(key, member)
|
56
322
|
end
|
57
323
|
|
58
|
-
def
|
59
|
-
|
324
|
+
def hset(key, field, value)
|
325
|
+
node_for(key).hset(key, field, value)
|
60
326
|
end
|
61
327
|
|
62
|
-
def
|
63
|
-
|
328
|
+
def hget(key, field)
|
329
|
+
node_for(key).hget(key, field)
|
64
330
|
end
|
65
|
-
alias_method :flushall, :flush_all
|
66
331
|
|
67
|
-
def
|
68
|
-
|
332
|
+
def hdel(key, field)
|
333
|
+
node_for(key).hdel(key, field)
|
69
334
|
end
|
70
|
-
alias_method :flushdb, :flush_db
|
71
335
|
|
72
|
-
def
|
73
|
-
|
74
|
-
red.keys("*").each do |key|
|
75
|
-
red.del key
|
76
|
-
end
|
77
|
-
end
|
336
|
+
def hexists(key, field)
|
337
|
+
node_for(key).hexists(key, field)
|
78
338
|
end
|
79
339
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
340
|
+
def hlen(key)
|
341
|
+
node_for(key).hlen(key)
|
342
|
+
end
|
343
|
+
|
344
|
+
def hkeys(key)
|
345
|
+
node_for(key).hkeys(key)
|
84
346
|
end
|
85
347
|
|
86
|
-
def
|
348
|
+
def hvals(key)
|
349
|
+
node_for(key).hvals(key)
|
350
|
+
end
|
87
351
|
|
352
|
+
def hgetall(key)
|
353
|
+
node_for(key).hgetall(key)
|
88
354
|
end
|
89
355
|
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
356
|
+
def hmset(key, *attrs)
|
357
|
+
node_for(key).hmset(key, *attrs)
|
358
|
+
end
|
359
|
+
|
360
|
+
def sort(key, options = {})
|
361
|
+
raise CannotDistribute, :sort
|
362
|
+
end
|
363
|
+
|
364
|
+
def multi(&block)
|
365
|
+
raise CannotDistribute, :multi
|
366
|
+
end
|
367
|
+
|
368
|
+
def exec
|
369
|
+
raise CannotDistribute, :exec
|
370
|
+
end
|
371
|
+
|
372
|
+
def discard
|
373
|
+
raise CannotDistribute, :discard
|
374
|
+
end
|
375
|
+
|
376
|
+
def publish(channel, message)
|
377
|
+
raise NotImplementedError
|
378
|
+
end
|
379
|
+
|
380
|
+
def unsubscribe(*channels)
|
381
|
+
raise NotImplementedError
|
382
|
+
end
|
383
|
+
|
384
|
+
def subscribe(*channels, &block)
|
385
|
+
raise NotImplementedError
|
386
|
+
end
|
387
|
+
|
388
|
+
def punsubscribe(*channels)
|
389
|
+
raise NotImplementedError
|
390
|
+
end
|
391
|
+
|
392
|
+
def psubscribe(*channels, &block)
|
393
|
+
raise NotImplementedError
|
394
|
+
end
|
395
|
+
|
396
|
+
def save
|
397
|
+
on_each_node :save
|
398
|
+
end
|
399
|
+
|
400
|
+
def bgsave
|
401
|
+
on_each_node :bgsave
|
402
|
+
end
|
403
|
+
|
404
|
+
def lastsave
|
405
|
+
on_each_node :lastsave
|
406
|
+
end
|
407
|
+
|
408
|
+
def info
|
409
|
+
on_each_node :info
|
410
|
+
end
|
411
|
+
|
412
|
+
def monitor
|
413
|
+
raise NotImplementedError
|
414
|
+
end
|
415
|
+
|
416
|
+
def echo(value)
|
417
|
+
on_each_node :echo, value
|
418
|
+
end
|
419
|
+
|
420
|
+
def pipelined
|
421
|
+
raise CannotDistribute, :pipelined
|
99
422
|
end
|
100
423
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
kbn[node] << k
|
107
|
-
kbn
|
424
|
+
protected
|
425
|
+
|
426
|
+
def on_each_node(command, *args)
|
427
|
+
nodes.map do |node|
|
428
|
+
node.send(command, *args)
|
108
429
|
end
|
109
430
|
end
|
110
431
|
|
111
|
-
def
|
112
|
-
|
432
|
+
def node_index_for(key)
|
433
|
+
nodes.index(node_for(key))
|
113
434
|
end
|
114
435
|
end
|
115
436
|
end
|