我正在尝试将现有密钥从Redis实例(A)移动到另一个实例(B)而不会丢失B的密钥。 我可以使用任何工具,还是应该自己编写代码?
答案 0 :(得分:0)
根据官方Redis群集教程:“...但是目前redis-trib无法自动重新平衡群集,检查群集节点上的密钥分配,并根据需要智能地移动插槽。此功能将被添加在将来。“
因此,您需要自己编写代码以将密钥分发给Redis实例。如果要将一个或多个密钥从一个节点迁移到另一个节点,则必须首先迁移哈希点,然后再迁移实际密钥,否则会发生错误。
通常,您需要一个执行这些Ruby代码行的代码过程(redis-trib.rb中的原型):
将插槽从源节点迁移到目标节点的代码
target.r.cluster("setslot",slot,"importing",source.info[:name])
source.r.cluster("setslot",slot,"migrating",target.info[:name])
迁移实际密钥的代码
source.r.client.call(["migrate",target.info[:host],target.info[:port],$keys_of_source[i],0,15000]).
您可以从此处使用现有代码进行迁移:https://github.com/projecteru/redis-trib.py
您可以使用以下代码行:
def migrate_slots_stable(src_host, src_port, dst_host, dst_port, slots):
if src_host == dst_host and src_port == dst_port:
raise ValueError('The source and the target node are the same. A good reason is that the key is stored already on target node!')
with Connection( src_host, src_port ) as t:
nodes, myself = _list_masters( t, src_host)
slots = set( slots )
print('\x1b[6;30;42m' + '*****************************************MIGRATION PROCEDURE******************************************' + '\x1b[0m')
print('\x1b[6;30;42m' + '******************************************************************************************************' + '\x1b[0m')
print '* Migrating slots: ', slots , "* \n"
for n in nodes:
if n.host == dst_host and n.port == dst_port:
return _migr_slots_stable( myself, n, slots, nodes )
#raise ValueError( 'Two nodes are not in the same cluster' )
def _migr_slots_stable(source_node, target_node, slots, nodes):
key_count = 0
for slot in slots:
key_count += _migr_one_slot_stable(source_node, target_node, slot, nodes)
_migr_one_slot_stable( source_node, target_node, slot, nodes )
#print "* keys_count that exists in these slot(s): ", key_count,' *'
#print "\n"
#print '* Migrated succesfully:',len(slots),'slot(s) and ',key_count,'key(s) from SOURCE NODE --> node_id:',source_node.node_id,'host:',source_node.host,'port:',source_node.port,'to TARGET NODE --> node_id:', target_node.node_id,'host:',target_node.host,'port:',target_node.port,' *'
#print('\x1b[6;30;42m' + '******************************************************************************************************' + '\x1b[0m')
print "\n"
def _migr_one_slot_stable(source_node, target_node, slot, nodes):
def expect_exec_ok(m, conn, slot):
if m.lower() != 'ok':
conn.raise_('\n'.join([
'Error while moving slot [ %d ] between' % slot,
'Source node - %s:%d' % (source_node.host, source_node.port),
'Target node - %s:%d' % (target_node.host, target_node.port),
'Got %s' % m]))
# Set the new node as the owner of the slot in all the known nodes
# Bind the hash slot to a different node
@retry(stop_max_attempt_number=16, wait_fixed=100)
def setslot_stable(conn, slot, node_id):
m = conn.execute('cluster', 'setslot', slot, 'node', node_id)
expect_exec_ok(m, conn, slot)
source_conn = source_node.get_conn()
target_conn = target_node.get_conn()
# Same in Ruby with these lines of code
# the target node importing the slot and the source node migrating it
try:
expect_exec_ok(
target_conn.execute('cluster', 'setslot', slot, 'importing',
source_node.node_id),
target_conn, slot)
except hiredis.ReplyError, e:
if 'already the owner of' not in e.message:
target_conn.raise_(e.message)
try:
expect_exec_ok(
source_conn.execute('cluster', 'setslot', slot, 'migrating',
target_node.node_id),
source_conn, slot)
except hiredis.ReplyError, e:
if 'not the owner of' not in e.message:
source_conn.raise_(e.message)
keys = _migr_keys_stable(source_conn, target_node.host, target_node.port, slot)
setslot_stable(source_conn, slot, target_node.node_id)
for node in nodes:
setslot_stable(node.get_conn(), slot, target_node.node_id)
return keys
def _migr_keys_stable(src_conn, target_host, target_port, slot):
key_count = 0
while True:
keys = src_conn.execute('cluster', 'getkeysinslot', slot, 10)
if len(keys) == 0:
return key_count
key_count += len(keys)
src_conn.execute_bulk(
# Same in Ruby with this line of code: source.r.client.call(["migrate",target.info[:host],target.info[:port],$keys_of_source[i],0,15000])
[['migrate', target_host, target_port, k, 0, 30000] for k in keys])
触发的第一个函数是def migrate_slots_stable
,并且具有源主机,源端口,目标主机,目标端口和要传输的一组哈希映射的参数。