Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
c68c7871
Commit
c68c7871
authored
May 21, 2014
by
antirez
Browse files
redis-trib fix improved: move keys from N nodes to owner.
parent
56161ca0
Changes
1
Show whitespace changes
Inline
Side-by-side
src/redis-trib.rb
View file @
c68c7871
...
...
@@ -139,10 +139,10 @@ class ClusterNode
if
s
[
0
..
0
]
==
'['
if
s
.
index
(
"->-"
)
# Migrating
slot
,
dst
=
s
[
1
..-
1
].
split
(
"->-"
)
@info
[
:migrating
][
slot
]
=
dst
@info
[
:migrating
][
slot
.
to_i
]
=
dst
elsif
s
.
index
(
"-<-"
)
# Importing
slot
,
src
=
s
[
1
..-
1
].
split
(
"-<-"
)
@info
[
:importing
][
slot
]
=
src
@info
[
:importing
][
slot
.
to_i
]
=
src
end
elsif
s
.
index
(
"-"
)
start
,
stop
=
s
.
split
(
"-"
)
...
...
@@ -445,10 +445,33 @@ class RedisTrib
end
end
# Return the owner of the specified slot
def
get_slot_owner
(
slot
)
@nodes
.
each
{
|
n
|
n
.
slots
.
each
{
|
s
,
_
|
return
n
if
s
==
slot
}
}
nil
end
# Slot 'slot' was found to be in importing or migrating state in one or
# more nodes. This function fixes this condition by migrating keys where
# it seems more sensible.
def
fix_open_slot
(
slot
)
puts
">>> Fixing open slot
#{
slot
}
"
# Try to obtain the current slot owner, according to the current
# nodes configuration.
owner
=
get_slot_owner
(
slot
)
# If there is no slot owner, set as owner the slot with the biggest
# number of keys, among the set of migrating / importing nodes.
if
!
owner
xputs
"*** Fix me, some work to do here."
exit
1
end
migrating
=
[]
importing
=
[]
@nodes
.
each
{
|
n
|
...
...
@@ -457,11 +480,11 @@ class RedisTrib
migrating
<<
n
elsif
n
.
info
[
:importing
][
slot
]
importing
<<
n
elsif
n
.
r
.
cluster
(
"countkeysinslot"
,
slot
)
>
0
elsif
n
.
r
.
cluster
(
"countkeysinslot"
,
slot
)
>
0
&&
n
!=
owner
xputs
"*** Found keys about slot
#{
slot
}
in node
#{
n
}
!"
importing
<<
n
end
}
puts
">>> Fixing open slot
#{
slot
}
"
puts
"Set as migrating in:
#{
migrating
.
join
(
","
)
}
"
puts
"Set as importing in:
#{
importing
.
join
(
","
)
}
"
...
...
@@ -469,12 +492,14 @@ class RedisTrib
# importing state in 1 slot. That's trivial to address.
if
migrating
.
length
==
1
&&
importing
.
length
==
1
move_slot
(
migrating
[
0
],
importing
[
0
],
slot
,
:verbose
=>
true
,
:fix
=>
true
)
elsif
migrating
.
length
==
1
&&
importing
.
length
==
0
xputs
">>> Setting
#{
slot
}
as STABLE"
migrating
[
0
].
r
.
cluster
(
"setslot"
,
slot
,
"stable"
)
elsif
migrating
.
length
==
0
&&
importing
.
length
==
1
xputs
">>> Setting
#{
slot
}
as STABLE"
elsif
migrating
.
length
==
0
&&
importing
.
length
>
0
xputs
">>> Moving all the
#{
slot
}
slot keys to its owner
#{
owner
}
"
importing
.
each
{
|
node
|
next
if
node
==
owner
move_slot
(
node
,
owner
,
slot
,
:verbose
=>
true
,
:fix
=>
true
,
:cold
=>
true
)
xputs
">>> Setting
#{
slot
}
as STABLE in
#{
node
}
"
importing
[
0
].
r
.
cluster
(
"setslot"
,
slot
,
"stable"
)
}
else
xputs
"[ERR] Sorry, Redis-trib can't fix this slot yet (work in progress)"
end
...
...
@@ -727,14 +752,22 @@ class RedisTrib
}
end
# Move slots between source and target nodes using MIGRATE.
#
# Options:
# :verbose -- Print a dot for every moved key.
# :fix -- We are moving in the context of a fix. Use REPLACE.
# :cold -- Move keys without opening / reconfiguring the nodes.
def
move_slot
(
source
,
target
,
slot
,
o
=
{})
# We start marking the slot as importing in the destination node,
# and the slot as migrating in the target host. Note that the order of
# the operations is important, as otherwise a client may be redirected
# to the target node that does not yet know it is importing this slot.
print
"Moving slot
#{
slot
}
from
#{
source
}
to
#{
target
}
: "
;
STDOUT
.
flush
if
!
o
[
:cold
]
target
.
r
.
cluster
(
"setslot"
,
slot
,
"importing"
,
source
.
info
[
:name
])
source
.
r
.
cluster
(
"setslot"
,
slot
,
"migrating"
,
target
.
info
[
:name
])
end
# Migrate all the keys from source to target using the MIGRATE command
while
true
keys
=
source
.
r
.
cluster
(
"getkeysinslot"
,
slot
,
10
)
...
...
@@ -756,12 +789,15 @@ class RedisTrib
STDOUT
.
flush
}
end
puts
# Set the new node as the owner of the slot in all the known nodes.
if
!
o
[
:cold
]
@nodes
.
each
{
|
n
|
n
.
r
.
cluster
(
"setslot"
,
slot
,
"node"
,
target
.
info
[
:name
])
}
end
end
# redis-trib subcommands implementations
...
...
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