Skip to content

Strange replication behavior with Lua and RM_Replicate() #4466

@mnunberg

Description

@mnunberg

This in itself may be two issues:

  1. RM_Replicate() opens a MULTI call which is never actually closed
  2. Commands executed within Lua scripts never actually get replicated unless another (builtin??) command is also invoked within it.

I've solved the first issue - I realized that RM_Replicate ended up calling propagate() which shouldn't be used in conjunction with alsoPropagate(). I'm still trying to figure out the second one.

Here's a Python script which demonstrates the issue:

#!/usr/bin/env python
from redis.client import StrictRedis

MASTER_PORT=7777
SLAVE_PORT=8888

rr_master = StrictRedis(port=MASTER_PORT)
rr_slave = StrictRedis(port=SLAVE_PORT)
rr_slave.execute_command('SLAVEOF', 'localhost', str(MASTER_PORT))
rr_master.execute_command('MY.CMDV')
rr_master.execute_command('MY.CMD')

rr_master.execute_command('EVAL', r'''
    redis.call("MY.CMDV", "fooScript");
    redis.call("MY.CMD", "barScript");
    print("Hello!!!");
''', '0')

This is assuming a very dumb module called 'MY':

#include "redismodule.h"

static int DummyCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    RedisModule_Replicate(ctx, "MY.CMD", "v", argv, argc);
    return RedisModule_ReplyWithSimpleString(ctx, "OK");
}

static int DummyCommandVerbatim(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    RedisModule_ReplicateVerbatim(ctx);
    return RedisModule_ReplyWithSimpleString(ctx, "OK");
}

int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (RedisModule_Init(ctx, "MY", 1, REDISMODULE_APIVER_1) != REDISMODULE_OK) {
        return REDISMODULE_ERR;
    }
    if (RedisModule_CreateCommand(ctx, "MY.CMD", DummyCommand, "write deny-oom", 1, 1, 1) != REDISMODULE_OK) {
        return REDISMODULE_ERR;
    }
    if (RedisModule_CreateCommand(ctx, "MY.CMDV", DummyCommandVerbatim, "write deny-oom", 1, 1, 1) != REDISMODULE_OK) {
        return REDISMODULE_ERR;
    }
    return REDISMODULE_OK;
}

MONITOR output on slave (after running the commands a few times)

1511374285.851288 [0 [::1]:7777] "PING"
1511374288.673754 [0 [::1]:7777] "SELECT" "0"
1511374288.673766 [0 [::1]:7777] "MY.CMDV"
1511374288.673877 [0 [::1]:7777] "MULTI"
1511374288.673888 [0 [::1]:7777] "MY.CMD" "MY.CMD"
1511374288.673896 [0 [::1]:7777] "EXEC"
1511374288.674053 [0 [::1]:7777] "MULTI"
1511374291.619535 [0 [::1]:7777] "MULTI"
1511374291.619545 [0 [::1]:7777] "MY.CMDV"
1511374291.619549 [0 [::1]:7777] "MY.CMD" "MY.CMD"
1511374291.619557 [0 [::1]:7777] "EXEC"
1511374291.619677 [0 [::1]:7777] "MULTI"

Making use of alsoPropagate rather than propagate:

1511374434.392146 [0 [::1]:7777] "MY.CMDV"
1511374434.392324 [0 [::1]:7777] "MULTI"
1511374434.392333 [0 [::1]:7777] "MY.CMD" "MY.CMD"
1511374434.392341 [0 [::1]:7777] "EXEC"

I'm wondering if perhaps Lua is also mixing the two APIs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions