Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
2a48bd4a
You need to sign in or sign up before continuing.
Commit
2a48bd4a
authored
May 10, 2014
by
antirez
Browse files
Cluster: initial ability to import data from standalone instance.
parent
71d0e7e0
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/redis-trib.rb
View file @
2a48bd4a
...
@@ -988,6 +988,47 @@ class RedisTrib
...
@@ -988,6 +988,47 @@ class RedisTrib
}
}
end
end
def
import_cluster_cmd
(
argv
,
opt
)
source_addr
=
opt
[
'from'
]
xputs
">>> Importing data from
#{
source_addr
}
to cluster
#{
argv
[
1
]
}
"
# Check the existing cluster.
load_cluster_info_from_node
(
argv
[
0
])
check_cluster
# Connect to the source node.
xputs
">>> Connecting to the source Redis instance"
src_host
,
src_port
=
source_addr
.
split
(
":"
)
source
=
Redis
.
new
(
:host
=>
src_host
,
:port
=>
src_port
)
if
source
.
info
[
'cluster_enabled'
].
to_i
==
1
xputs
"[ERR] The source node should not be a cluster node."
end
xputs
"*** Importing
#{
source
.
dbsize
}
keys from DB 0"
# Build a slot -> node map
slots
=
{}
@nodes
.
each
{
|
n
|
n
.
slots
.
each
{
|
s
,
_
|
slots
[
s
]
=
n
}
}
# Use SCAN to iterate over the keys, migrating to the
# right node as needed.
cursor
=
nil
while
cursor
!=
0
cursor
,
keys
=
source
.
scan
(
cursor
,
:count
,
1000
)
cursor
=
cursor
.
to_i
keys
.
each
{
|
k
|
# Migrate keys using the MIGRATE command.
slot
=
key_to_slot
(
k
)
target
=
slots
[
slot
]
puts
"Migrating
#{
k
}
to
#{
target
}
"
source
.
client
.
call
([
"migrate"
,
target
.
info
[
:host
],
target
.
info
[
:port
],
k
,
0
,
1000
])
}
end
end
def
help_cluster_cmd
(
argv
,
opt
)
def
help_cluster_cmd
(
argv
,
opt
)
show_help
show_help
exit
0
exit
0
...
@@ -1021,16 +1062,107 @@ class RedisTrib
...
@@ -1021,16 +1062,107 @@ class RedisTrib
end
end
# Enforce mandatory options
# Enforce mandatory options
ALLOWED_OPTIONS
[
cmd
].
each
{
|
option
,
val
|
if
ALLOWED_OPTIONS
[
cmd
]
if
!
options
[
option
]
&&
val
==
:required
ALLOWED_OPTIONS
[
cmd
].
each
{
|
option
,
val
|
puts
"Option '--
#{
option
}
' is required for subcommand '
#{
cmd
}
'"
if
!
options
[
option
]
&&
val
==
:required
exit
1
puts
"Option '--
#{
option
}
' is required "
+
\
end
"for subcommand '
#{
cmd
}
'"
}
exit
1
end
}
end
return
options
,
idx
return
options
,
idx
end
end
end
end
#################################################################################
# Libraries
#
# We try to don't depend on external libs since this is a critical part
# of Redis Cluster.
#################################################################################
# This is the CRC16 algorithm used by Redis Cluster to hash keys.
# Implementation according to CCITT standards.
#
# This is actually the XMODEM CRC 16 algorithm, using the
# following parameters:
#
# Name : "XMODEM", also known as "ZMODEM", "CRC-16/ACORN"
# Width : 16 bit
# Poly : 1021 (That is actually x^16 + x^12 + x^5 + 1)
# Initialization : 0000
# Reflect Input byte : False
# Reflect Output CRC : False
# Xor constant to output CRC : 0000
# Output for "123456789" : 31C3
module
RedisClusterCRC16
def
RedisClusterCRC16
.
crc16
(
bytes
)
crc
=
0
bytes
.
each_byte
{
|
b
|
crc
=
((
crc
<<
8
)
&
0xffff
)
^
XMODEMCRC16Lookup
[((
crc
>>
8
)
^
b
)
&
0xff
]
}
crc
end
private
XMODEMCRC16Lookup
=
[
0x0000
,
0x1021
,
0x2042
,
0x3063
,
0x4084
,
0x50a5
,
0x60c6
,
0x70e7
,
0x8108
,
0x9129
,
0xa14a
,
0xb16b
,
0xc18c
,
0xd1ad
,
0xe1ce
,
0xf1ef
,
0x1231
,
0x0210
,
0x3273
,
0x2252
,
0x52b5
,
0x4294
,
0x72f7
,
0x62d6
,
0x9339
,
0x8318
,
0xb37b
,
0xa35a
,
0xd3bd
,
0xc39c
,
0xf3ff
,
0xe3de
,
0x2462
,
0x3443
,
0x0420
,
0x1401
,
0x64e6
,
0x74c7
,
0x44a4
,
0x5485
,
0xa56a
,
0xb54b
,
0x8528
,
0x9509
,
0xe5ee
,
0xf5cf
,
0xc5ac
,
0xd58d
,
0x3653
,
0x2672
,
0x1611
,
0x0630
,
0x76d7
,
0x66f6
,
0x5695
,
0x46b4
,
0xb75b
,
0xa77a
,
0x9719
,
0x8738
,
0xf7df
,
0xe7fe
,
0xd79d
,
0xc7bc
,
0x48c4
,
0x58e5
,
0x6886
,
0x78a7
,
0x0840
,
0x1861
,
0x2802
,
0x3823
,
0xc9cc
,
0xd9ed
,
0xe98e
,
0xf9af
,
0x8948
,
0x9969
,
0xa90a
,
0xb92b
,
0x5af5
,
0x4ad4
,
0x7ab7
,
0x6a96
,
0x1a71
,
0x0a50
,
0x3a33
,
0x2a12
,
0xdbfd
,
0xcbdc
,
0xfbbf
,
0xeb9e
,
0x9b79
,
0x8b58
,
0xbb3b
,
0xab1a
,
0x6ca6
,
0x7c87
,
0x4ce4
,
0x5cc5
,
0x2c22
,
0x3c03
,
0x0c60
,
0x1c41
,
0xedae
,
0xfd8f
,
0xcdec
,
0xddcd
,
0xad2a
,
0xbd0b
,
0x8d68
,
0x9d49
,
0x7e97
,
0x6eb6
,
0x5ed5
,
0x4ef4
,
0x3e13
,
0x2e32
,
0x1e51
,
0x0e70
,
0xff9f
,
0xefbe
,
0xdfdd
,
0xcffc
,
0xbf1b
,
0xaf3a
,
0x9f59
,
0x8f78
,
0x9188
,
0x81a9
,
0xb1ca
,
0xa1eb
,
0xd10c
,
0xc12d
,
0xf14e
,
0xe16f
,
0x1080
,
0x00a1
,
0x30c2
,
0x20e3
,
0x5004
,
0x4025
,
0x7046
,
0x6067
,
0x83b9
,
0x9398
,
0xa3fb
,
0xb3da
,
0xc33d
,
0xd31c
,
0xe37f
,
0xf35e
,
0x02b1
,
0x1290
,
0x22f3
,
0x32d2
,
0x4235
,
0x5214
,
0x6277
,
0x7256
,
0xb5ea
,
0xa5cb
,
0x95a8
,
0x8589
,
0xf56e
,
0xe54f
,
0xd52c
,
0xc50d
,
0x34e2
,
0x24c3
,
0x14a0
,
0x0481
,
0x7466
,
0x6447
,
0x5424
,
0x4405
,
0xa7db
,
0xb7fa
,
0x8799
,
0x97b8
,
0xe75f
,
0xf77e
,
0xc71d
,
0xd73c
,
0x26d3
,
0x36f2
,
0x0691
,
0x16b0
,
0x6657
,
0x7676
,
0x4615
,
0x5634
,
0xd94c
,
0xc96d
,
0xf90e
,
0xe92f
,
0x99c8
,
0x89e9
,
0xb98a
,
0xa9ab
,
0x5844
,
0x4865
,
0x7806
,
0x6827
,
0x18c0
,
0x08e1
,
0x3882
,
0x28a3
,
0xcb7d
,
0xdb5c
,
0xeb3f
,
0xfb1e
,
0x8bf9
,
0x9bd8
,
0xabbb
,
0xbb9a
,
0x4a75
,
0x5a54
,
0x6a37
,
0x7a16
,
0x0af1
,
0x1ad0
,
0x2ab3
,
0x3a92
,
0xfd2e
,
0xed0f
,
0xdd6c
,
0xcd4d
,
0xbdaa
,
0xad8b
,
0x9de8
,
0x8dc9
,
0x7c26
,
0x6c07
,
0x5c64
,
0x4c45
,
0x3ca2
,
0x2c83
,
0x1ce0
,
0x0cc1
,
0xef1f
,
0xff3e
,
0xcf5d
,
0xdf7c
,
0xaf9b
,
0xbfba
,
0x8fd9
,
0x9ff8
,
0x6e17
,
0x7e36
,
0x4e55
,
0x5e74
,
0x2e93
,
0x3eb2
,
0x0ed1
,
0x1ef0
]
end
# Turn a key name into the corrisponding Redis Cluster slot.
def
key_to_slot
(
key
)
# Only hash what is inside {...} if there is such a pattern in the key.
# Note that the specification requires the content that is between
# the first { and the first } after the first {. If we found {} without
# nothing in the middle, the whole key is hashed as usually.
s
=
key
.
index
"{"
if
s
e
=
key
.
index
"}"
,
s
+
1
if
e
&&
e
!=
s
+
1
key
=
key
[
s
+
1
..
e
-
1
]
end
end
RedisClusterCRC16
.
crc16
(
key
)
%
16384
end
#################################################################################
# Definition of commands
#################################################################################
COMMANDS
=
{
COMMANDS
=
{
"create"
=>
[
"create_cluster_cmd"
,
-
2
,
"host1:port1 ... hostN:portN"
],
"create"
=>
[
"create_cluster_cmd"
,
-
2
,
"host1:port1 ... hostN:portN"
],
"check"
=>
[
"check_cluster_cmd"
,
2
,
"host:port"
],
"check"
=>
[
"check_cluster_cmd"
,
2
,
"host:port"
],
...
@@ -1040,12 +1172,14 @@ COMMANDS={
...
@@ -1040,12 +1172,14 @@ COMMANDS={
"del-node"
=>
[
"delnode_cluster_cmd"
,
3
,
"host:port node_id"
],
"del-node"
=>
[
"delnode_cluster_cmd"
,
3
,
"host:port node_id"
],
"set-timeout"
=>
[
"set_timeout_cluster_cmd"
,
3
,
"host:port milliseconds"
],
"set-timeout"
=>
[
"set_timeout_cluster_cmd"
,
3
,
"host:port milliseconds"
],
"call"
=>
[
"call_cluster_cmd"
,
-
3
,
"host:port command arg arg .. arg"
],
"call"
=>
[
"call_cluster_cmd"
,
-
3
,
"host:port command arg arg .. arg"
],
"import"
=>
[
"import_cluster_cmd"
,
2
,
"host:port"
],
"help"
=>
[
"help_cluster_cmd"
,
1
,
"(show this help)"
]
"help"
=>
[
"help_cluster_cmd"
,
1
,
"(show this help)"
]
}
}
ALLOWED_OPTIONS
=
{
ALLOWED_OPTIONS
=
{
"create"
=>
{
"replicas"
=>
true
},
"create"
=>
{
"replicas"
=>
true
},
"add-node"
=>
{
"slave"
=>
false
,
"master-id"
=>
true
}
"add-node"
=>
{
"slave"
=>
false
,
"master-id"
=>
true
},
"import"
=>
{
"from"
=>
:required
}
}
}
def
show_help
def
show_help
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment