我们在生产环境中广泛使用redis-cluster。我们目前有30个节点集群(15个主节点,15个从节点) 我们正在尝试增加集群,为此,我们创建了新服务器并将它们加入集群。到目前为止一切都很好。
下一步-我们正尝试将插槽重新分配给新的母版。我们使用redis-trib
reshard
命令编写了执行此操作的脚本。
但是-迁移中途失败(但距离开始不远),并出现以下错误:
[ERR] Calling MIGRATE: ERR Target instance replied with error: BUSYKEY Target key name already exists.
这种情况偶尔发生,有时它会在失败之前设法移动一些插槽,有时会在第一个插槽上发生故障。 每个此类故障都需要手动修复操作,这使得重新分片操作非常难以管理。
除了停机时间迁移之外,我们没有找到任何具体的例子,也没有任何有关如何防止这种情况的想法。我们正在努力避免。
版本:
Redis服务器4.0.2
redis trib 3.3.3(在此问题之后从4.0.2降级:redis cluster reshard [ERR] Calling MIGRATE: ERR Syntax error)
我们的下一步是升级到最新的Redis(4.0.11),即使在此问题的发行说明中没有发现任何迹象。
希望听到我们做错了什么以及如何解决它,或者redis-cluster是否不是为实时重新分片而构建的?
谢谢
答案 0 :(得分:0)
在为我们自己的项目提供redis集群支持时,我遇到了类似的问题。我发现redis-trib reshard
命令存在问题。如果没有密钥存储在从一个主服务器迁移到另一个主服务器的插槽中,它会很好地工作。
但是redis-5(仍在开发中,尚不稳定)拥有自己的 我认为`redis-cli'与分片命令没有问题。仅适用于5的较低版本。
如果您查看Redis的官方文档,说redis reconfiguration和redis cluster resharding,您会发现它们在内部进行重新分片。
因此,我通过运行bash脚本而不是运行redis-trib reshard
命令来完成这些任务,从而解决了问题。
假设您想将一些插槽从主节点重新分片到其他主节点。我们将拥有哈希槽当前所有权的节点称为源节点,并将要迁移目标节点的节点称为
。对于每个插槽,请执行以下步骤:
请记住,根据redis官方文档,这些步骤的顺序在这里很重要。
CLUSTER SETSLOT <slot> IMPORTING <source-node-id>
到目的地节点,将广告位设置为导入状态。CLUSTER SETSLOT <slot> MIGRATING <destination-node-id>
到源节点以将广告位设置为正在迁移状态。使用CLUSTER GETKEYSINSLOT命令从源节点获取密钥,然后使用以下MIGRATE命令将其移至目标节点。
MIGRATE target_host target_port key target_database_id timeout
在Redis Cluster中,无需指定0以外的数据库,但是MIGRATE是通用命令,可用于不涉及Redis Cluster的其他任务。
CLUSTER SETSLOT <slot> NODE <destination-node-id>
,以便将插槽再次设置为正常状态。通常会将同一命令发送给所有其他节点,以避免等待新配置在集群中自然传播。这里也提供了一个简单的bash脚本示例:
source-ip:172.17.0.5
。来源ID:1f70a5107e0042a7d33a9efaf88dbdfecd78076a
destination-ip:172.17.0.4
。 destination-id:7e428bae84697a3882ecad19bd0d13ac7ee97d02
另一个主IP:172.17.0.7
for i in `seq 0 5460`; do
redis-cli -c -h 172.17.0.4 cluster setslot ${i} importing 1f70a5107e0042a7d33a9efaf88dbdfecd78076a
redis-cli -c -h 172.17.0.5 cluster setslot ${i} migrating 7e428bae84697a3882ecad19bd0d13ac7ee97d02
while true; do
key=`redis-cli -c -h 172.17.0.5 cluster getkeysinslot ${i} 1`
if [ "" = "$key" ]; then
echo "there are no key in this slot ${i}"
break
fi
redis-cli -h 172.17.0.5 migrate 172.17.0.4 6379 ${key} 0 5000
done
redis-cli -c -h 172.17.0.5 cluster setslot ${i} node 7e428bae84697a3882ecad19bd0d13ac7ee97d02
redis-cli -c -h 172.17.0.4 cluster setslot ${i} node 7e428bae84697a3882ecad19bd0d13ac7ee97d02
redis-cli -c -h 172.17.0.7 cluster setslot ${i} node 7e428bae84697a3882ecad19bd0d13ac7ee97d02
done