Redis 3.0.7版不支持带密码的cluster rebalance操作

杜辰龙
2023-12-01

一、前言

因业务需要扩容,考虑到集群单实例容量已经超过10GB,算是比较大的情况了。所以不能直接调整maxmemory参数进行扩容,需要加节点动态扩容。

业务集群版本是3.0.7版本的。

二、操作

2.1 模拟和执行

在对3.0.7版带密码的集群加好新主从,模拟迁槽位没有问题:

./redis-trib.rb rebalance --password "xxx" --use-empty-masters --simulate xx:xx1
...
...

但是真正执行的时候出问题了:

./redis-trib.rb rebalance --password "xxx" --use-empty-masters xx:xx1
>>> Performing Cluster Check (using node xx:xx1)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
[WARNING] Node xx:xx1 has slots in migrating state (13107).
[WARNING] Node xx:xx2 has slots in importing state (13107).
[WARNING] The following slots are open: 13107
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** Please fix your cluster problems before rebalancing

错误输出提示需要先 fix 集群的问题才能继续做rebalance操作。

2.2 fix

进行fix操作

./redis-trib.rb fix --password "xxx" xx:xx1
>>> Fixing open slot 13107
Set as migrating in: xx:xx1
Set as importing in: xx:xx2
Moving slot 13107 from xx:xx to xx:xx1: 
[ERR] Calling MIGRATE: ERR syntax error

直接执行redis-trib.rb fix没效果

执行check看下情况

./redis-trib.rb check --password "xxx" xx:xx1
>>> Check for open slots...
[WARNING] Node xx:xx1 has slots in importing state (13107).
[WARNING] Node xx:xx2 has slots in migrating state (13107).
[WARNING] The following slots are open: 13107
>>> Check slots coverage...
[OK] All 16384 slots covered.

发现虽然All 16384 slots covere,但是仍然有两个节点上的13107槽位处于open状态,此时无法执行rebalance操作。

需要登录到对应的节点上执行如下命令,以修复open的slot

xx:xx1> cluster setslot 13107 stable
xx:xx2> cluster setslot  13107 stable

之后再次尝试rebalance操作,还是有报错,怀疑是redis-trib.rb工具不支持3版本有密码的rebalance操作。

2.3 换5版本的redis-cli继续尝试

5版本的Redis已经把redis-trib.rb集成到redis-cli命令里面了,相当的方便,用法如下:

./redis-cli --cluster help
Cluster Manager Commands:
  create         host1:port1 ... hostN:portN
                 --cluster-replicas <arg>
  check          host:port
                 --cluster-search-multiple-owners
  info           host:port
  fix            host:port
                 --cluster-search-multiple-owners
  reshard        host:port
                 --cluster-from <arg>
                 --cluster-to <arg>
                 --cluster-slots <arg>
                 --cluster-yes
                 --cluster-timeout <arg>
                 --cluster-pipeline <arg>
                 --cluster-replace
  rebalance      host:port
                 --cluster-weight <node1=w1...nodeN=wN>
                 --cluster-use-empty-masters
                 --cluster-timeout <arg>
                 --cluster-simulate
                 --cluster-pipeline <arg>
                 --cluster-threshold <arg>
                 --cluster-replace
  add-node       new_host:new_port existing_host:existing_port
                 --cluster-slave
                 --cluster-master-id <arg>
  del-node       host:port node_id
  call           host:port command arg arg .. arg
  set-timeout    host:port milliseconds
  import         host:port
                 --cluster-from <arg>
                 --cluster-copy
                 --cluster-replace
  help           

For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

使用redis-cli --cluster rebalance命令,还是一样的结果,加上simulate参数模拟的时候是可以操作,但是真正执行的时候就是会有问题。

这时候怀疑3版本的Redis就是不支持带密码的rebalance操作。

2.4 查看源码

3版本的/src/cluster.c 文件中的 migrateCommand(redisClient *c)

/* MIGRATE host port key dbid timeout [COPY | REPLACE]
 *
 * On in the multiple keys form:
 *
 * MIGRATE host port "" dbid timeout [COPY | REPLACE] KEYS key1 key2 ... keyN */
void migrateCommand(redisClient *c) {
    migrateCachedSocket *cs;
    int copy, replace, j;
    long timeout;
    long dbid;
    long long ttl, expireat;
    robj **ov = NULL; /* Objects to migrate. */
    robj **kv = NULL; /* Key names. */
    robj **newargv = NULL; /* Used to rewrite the command as DEL ... keys ... */
    rio cmd, payload;
    int may_retry = 1;
    int write_error = 0;

4版本的/src/cluster.c 文件中的 migrateCommand(redisClient *c)

/* MIGRATE host port key dbid timeout [COPY | REPLACE | AUTH password]
 *
 * On in the multiple keys form:
 *
 * MIGRATE host port "" dbid timeout [COPY | REPLACE | AUTH password] KEYS key1
 * key2 ... keyN */
void migrateCommand(client *c) {
    migrateCachedSocket *cs;
    int copy = 0, replace = 0, j;
    char *password = NULL;
    long timeout;
    long dbid;
    robj **ov = NULL; /* Objects to migrate. */
    robj **kv = NULL; /* Key names. */
    robj **newargv = NULL; /* Used to rewrite the command as DEL ... keys ... */
    rio cmd, payload;
    int may_retry = 1;
    int write_error = 0;
    int argv_rewritten = 0;

可以看到,3版本的migrateCommand函数就没有支持password,4版本就有AUTH password这个选项

三、总结

3.0.7版本的Redis不支持带密码的migrate类型的操作,4版本之后的支持。

具体是 4.0.7 版本之后才支持的

>= 3.0.0: Added the COPY and REPLACE options.
>= 3.0.6: Added the KEYS option.
>= 4.0.7: Added the AUTH option.
>= 6.0.0: Added the AUTH2 option.

参考 https://juejin.im/post/6844904079202713614

 类似资料: