Skip to content

Commit c781880

Browse files
author
Alva
committed
feat: add Redis Cluster support
- Added RedisClusterConnection type and cluster-specific command implementations - Implemented CRC16-based slot calculation for Redis Cluster key distribution - Added special handling for multi-key commands (mget, mset, del, etc.) to work across different slots - Created CLUSTER_MULTI_KEY_COMMANDS set to identify commands needing cluster-specific logic - Added cluster-aware implementations for key management commands (keys, rename, random
1 parent 2f5ab2a commit c781880

File tree

7 files changed

+1405
-18
lines changed

7 files changed

+1405
-18
lines changed

src/Redis.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ using MbedTLS
66
import Base.get, Base.keys, Base.time
77

88
export RedisException, ConnectionException, ServerException, ProtocolException, ClientException
9-
export RedisConnection, SentinelConnection, TransactionConnection, SubscriptionConnection,
9+
export RedisConnection, SentinelConnection, TransactionConnection, SubscriptionConnection, RedisClusterConnection,
1010
disconnect, is_connected, open_transaction, reset_transaction, open_subscription,
1111
open_pipeline, read_pipeline
1212
# Key commands
@@ -65,5 +65,6 @@ include("connection.jl")
6565
include("parser.jl")
6666
include("client.jl")
6767
include("commands.jl")
68+
include("cluster_commands.jl")
6869

6970
end

src/client.jl

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,38 @@
11
import DataStructures.OrderedSet
22

3+
const CLUSTER_MULTI_KEY_COMMANDS = Set([
4+
# String commands - multi-key operations
5+
"mget", "mset", "msetnx",
6+
7+
# Key commands - require same slot or special handling
8+
"del", "rename", "renamenx", "keys", "randomkey",
9+
10+
# List commands - require same slot
11+
"rpoplpush", "brpoplpush",
12+
13+
# Set commands - multi-key operations
14+
"smove", "sdiff", "sinter", "sunion",
15+
"sdiffstore", "sinterstore", "sunionstore",
16+
17+
# HyperLogLog commands - multi-key operations
18+
"pfcount", "pfmerge",
19+
20+
# Sorted Set commands - multi-key operations
21+
"zinterstore", "zunionstore",
22+
23+
# Bit commands - multi-key operations
24+
"bitop",
25+
26+
# Script commands - may involve multiple keys
27+
"eval", "evalsha",
28+
29+
# Server commands - need to broadcast to all nodes
30+
"flushall", "flushdb", "_time",
31+
32+
# Pub/Sub commands - need special handling
33+
"publish"
34+
])
35+
336
flatten(token) = string(token)
437
flatten(token::Vector{UInt8}) = [token]
538
flatten(token::String) = token
@@ -171,11 +204,14 @@ end
171204
macro redisfunction(command::AbstractString, ret_type, args...)
172205
is_exec = Symbol(command) == :exec
173206
func_name = esc(Symbol(command))
174-
command = lstrip(command,'_')
175-
command = split(command, '_')
207+
command_str = lstrip(command, '_')
208+
command = split(command_str, '_')
209+
210+
# Check if command needs special cluster handling (multi-key commands)
211+
needs_special_cluster_handling = command_str in CLUSTER_MULTI_KEY_COMMANDS
176212

177213
if length(args) > 0
178-
return quote
214+
base_functions = quote
179215
function $(func_name)(conn::RedisConnection, $(args...))
180216
response = execute_command(conn, flatten_command($(command...), $(args...)))
181217
convert_response($ret_type, response)
@@ -191,6 +227,17 @@ macro redisfunction(command::AbstractString, ret_type, args...)
191227
execute_command_without_reply(conn, flatten_command($(command...), $(args...)))
192228
end
193229
end
230+
231+
if !needs_special_cluster_handling
232+
push!(base_functions.args, :(
233+
function $(func_name)(conn::RedisClusterConnection, $(args...))
234+
response = execute_command(conn, flatten_command($(command...), $(args...)))
235+
convert_response($ret_type, response)
236+
end
237+
))
238+
end
239+
return base_functions
240+
194241
else
195242
q1 = quote
196243
function $(func_name)(conn::RedisConnection)
@@ -209,12 +256,24 @@ macro redisfunction(command::AbstractString, ret_type, args...)
209256
conn.num_commands += 1
210257
end
211258
end
259+
260+
exprs = [q1.args[2]]
261+
if !needs_special_cluster_handling
262+
q1_cluster = quote
263+
function $(func_name)(conn::RedisClusterConnection)
264+
response = execute_command(conn, flatten_command($(command...)))
265+
convert_response($ret_type, response)
266+
end
267+
end
268+
push!(exprs, q1_cluster.args[2])
269+
end
270+
212271
# To avoid redefining `function exec(conn::TransactionConnection)`
213-
if is_exec
214-
return Expr(:block, q1.args[2], q3.args[2])
215-
else
216-
return Expr(:block, q1.args[2], q2.args[2], q3.args[2])
272+
if !is_exec
273+
push!(exprs, q2.args[2])
217274
end
275+
push!(exprs, q3.args[2])
276+
return Expr(:block, exprs...)
218277
end
219278
end
220279

0 commit comments

Comments
 (0)