Redis 主从复制——masteruser

默认情况下,主从节点的连接用户是 default 用户,但在很多生产环境中 default 用户都会被禁止(禁用)使用。同时为了遵循权限最小原则,建议为主从复制专门设置一个用户用于连接认证。在 Redis 中,可以配置从节点以哪个用户连接主节点,该配置为 masteruser

主从复制配置

在 Redis 主从复制中,可以指定主从复制的连接用户,即从节点以什么用户连接主节点。默认是 default 用户,但也可指定其他用户。如何指定呢?

需要主从节点都配置 ACL,设置用户密码以及权限。例如,设置一个专门用于主从复制的用户 replica,并授予其主从复制所必需的命令权限:

postgres@slpc:/etc/redis$ sudo cat users.acl
user replica on #0ac34389d10624a1f24a923b63b0d8a739350686f8149ef4149f6c4a3703a42e ~* &* -@all +replconf +psync +ping

redis.conf 中添加如下配置:

masteruser replica   # 指定从节点连接主节点所使用的用户
masterauth <PASSWORD>

主从复制的日志分析

从节点日志:

130232:S 21 Jan 2026 14:26:04.515 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
130232:S 21 Jan 2026 14:26:04.515 * Ready to accept connections
130232:S 21 Jan 2026 14:26:04.516 - DB 0: 2 keys (0 volatile) in 4 slots HT.
130232:S 21 Jan 2026 14:26:04.516 * Connecting to MASTER 192.168.232.128:6379    # 连接主节点
130232:S 21 Jan 2026 14:26:04.516 * MASTER <-> REPLICA sync started
130232:S 21 Jan 2026 14:26:04.517 * Non blocking connect for SYNC fired the event.
130232:S 21 Jan 2026 14:26:04.518 * Master replied to PING, replication can continue...
130232:S 21 Jan 2026 14:26:04.519 * Trying a partial resynchronization (request 41d1777223513929c644c859b467a1eed109a8e0:13885).
130232:S 21 Jan 2026 14:26:04.520 * Successful partial resynchronization with master.
130232:S 21 Jan 2026 14:26:04.520 # Master replication ID changed to adbfa6dda0b49450836902276f0cf2040e554271
130232:S 21 Jan 2026 14:26:04.520 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization.

主节点日志:

166002:M 21 Jan 2026 14:26:03.553 * Ready to accept connections
166002:M 21 Jan 2026 14:26:03.553 - DB 0: 2 keys (0 volatile) in 4 slots HT.
166002:M 21 Jan 2026 14:26:04.495 - Accepted 192.168.232.137:40060
166002:M 21 Jan 2026 14:26:04.498 * Replica 192.168.232.137:6379 asks for synchronization
166002:M 21 Jan 2026 14:26:04.498 * Partial resynchronization request from 192.168.232.137:6379 accepted. Sending 0 bytes of backlog starting from offset 13885.
166002:M 21 Jan 2026 14:26:04.509 - Accepted 192.168.232.138:56888
166002:M 21 Jan 2026 14:26:04.512 * Replica 192.168.232.138:6379 asks for synchronization
166002:M 21 Jan 2026 14:26:04.513 * Partial resynchronization request from 192.168.232.138:6379 accepted. Sending 0 bytes of backlog starting from offset 13885.

源代码分析

当执行 replicaof 命令时,会调用 replicaofCommand 函数:

replicaofCommand(client *c)
--> replicationSetMaster(c->argv[1]->ptr, port);
    --> connectWithMaster();    // 连接 master
        // 发起连接,传入主节点 ip、port
        --> connConnect(server.repl_transfer_s, server.masterhost, server.masterport, server.bind_source_addr, syncWithMaster)

当连接成功后,会调用 syncWithMaster 函数:

void syncWithMaster(connection *conn) {

    /* If this event fired after the user turned the instance into a master
     * with SLAVEOF NO ONE we must just return ASAP. */
    if (server.repl_state == REPL_STATE_NONE) {
        connClose(conn);
        return;
    }

    // 发送 AUTH 命令
    // 从节点向主节点进行认证:如果配置了 masteruser,则使用 masteruser 用户进行认证,
    // 密码为读取 masterauth 配置得到的值
    if (server.repl_state == REPL_STATE_SEND_HANDSHAKE) {
        /* AUTH with the master if required. */
        if (server.masterauth) {
            char *args[3] = {"AUTH",NULL,NULL};
            size_t lens[3] = {4,0,0};
            int argc = 1;
            if (server.masteruser) {  // 添加认证用户
                args[argc] = server.masteruser;
                lens[argc] = strlen(server.masteruser);
                argc++;
            }
            args[argc] = server.masterauth; // 添加认证密码
            lens[argc] = sdslen(server.masterauth);
            argc++;
            err = sendCommandArgv(conn, argc, args, lens); // 向主节点发送认证信息
            if (err) goto write_error;
        }

        // 发送 REPLCONF 命令
        // 1. 告诉主节点,从节点的监听 port
        sendCommand(conn,"REPLCONF",
                    "listening-port",portstr, NULL);
        // 2. 告诉主节点,从节点能力信息:
        sendCommand(conn,"REPLCONF",
                "capa","eof","capa","psync2",NULL);

    }

    // 尝试进行部分同步,会向主节点发送 PSYNC 命令
    slaveTryPartialResynchronization(conn,1);
}