kvrocks icon indicating copy to clipboard operation
kvrocks copied to clipboard

EVALSHA allows to run if all commands are readonly in replica

Open git-hulk opened this issue 8 months ago • 12 comments

Search before asking

  • [x] I had searched in the issues and found no similar issues.

Motivation

Redis allows the EVALSHA/EVAL command to run the read-only commands in replica, but Kvrocks don't. So we would like to support this to keep consistent behavior with Redis.

For more context, please refer to: https://lists.apache.org/thread/f6n8qpl2fnho472b63o7r4d7ygsqz3t4

Solution

No response

Are you willing to submit a PR?

  • [ ] I'm willing to submit a PR!

git-hulk avatar Apr 01 '25 04:04 git-hulk

Hi @git-hulk ,

It seems that Apache James is pending by this issue.

I want to try with my best on this issue and hope it could help. 😊

Best Regards, Edward

LindaSummer avatar Apr 01 '25 06:04 LindaSummer

@LindaSummer Assigned, thank you!

git-hulk avatar Apr 01 '25 06:04 git-hulk

Hi @git-hulk ,

I have read through redis code and kvrocks code and found the difference.

Kvrocks checks the script command EVALSHA/EVAL and EVALSHA_RO/EVAL_RO before script execution. Redis discards the command's read or write attribution and check the command invoked by lua script in runtime.

Here is redis logic. It is called by lua_pcall in lua runtime.

struct redisCommand *cmd = lookupCommand(c->argv, c->argc);
......
......
if (scriptVerifyWriteCommandAllow(run_ctx, err) != C_OK) {
        goto error;
}

It checks the command which are called by lua script in runtime.

For example, if we run EVAL "return redis.call('GET', KEYS[1])" 1 mykey, redis will check GET during execution rather than EVAL ahead of script execution.

In kvrocks, I plan to add logic here and add a new option restrict-ro-script. If it is enabled, we will check the script command like EVAL and EVAL_RO before executing the script with current behavior. If it is disabled, we will bypass the EVAL_RO to EVAL and pass the node's role to lua context and check the command's behavior in runtime.

Before implementation, I would like to share my draft idea and please let me know if this idea has any problem.

Wish you a good day! 😊

Best Regards, Edward

LindaSummer avatar Apr 15 '25 12:04 LindaSummer

@LindaSummer Sounds good to me, thank you!

git-hulk avatar Apr 16 '25 10:04 git-hulk

从服务器无法使用 LUA 代码,即使设置 slave-read-only no ,依然会报错: READONLY You can't write against a read only slave

这个问题大概几时能解决?

haodiao avatar Sep 14 '25 07:09 haodiao

Sorry for the delay on this problem. I will continue working on this issue in recent.

LindaSummer avatar Nov 03 '25 07:11 LindaSummer

@haodiao For read-only commands, I think you can use EVAL_RO and EVALSHA_RO in replica.

PragmaTwice avatar Nov 03 '25 08:11 PragmaTwice

@PragmaTwice 在 从服务器 上无法使用 script load ,那怎么使用 evalsha_ro 呢?

haodiao avatar Nov 03 '25 08:11 haodiao

You can:

  • use EVAL_RO instead;
  • use EVALSHA_RO in replica after SCRIPT LOAD in master.

PragmaTwice avatar Nov 03 '25 09:11 PragmaTwice

  • use EVALSHA_RO in replica after SCRIPT LOAD in master.

原来可以这样的啊,这我到没有测试过,但我记得 redis 在 主服务器script load 的 lua 是不会同步到 从服务器 上的。
有时间我去修改一下我的代码了,感谢!

haodiao avatar Nov 08 '25 09:11 haodiao

You can also use FUNCTION LOAD and FCALL_RO.

PragmaTwice avatar Nov 08 '25 13:11 PragmaTwice

在这里我报告一个 bug 吧,不想再开一个issues 了,问题就是,使用 msgpack 编码之后,在 kvrocks lua 中无法解包。 当 msgpack 编码的数组中包含有二进制的元素,那么使用 local ok, unpacked = pcall(cmsgpack.unpack, data) 无法解包 ok=false,unpacked 打印出错误 Bad data format in input. 当 msgpack 编码的数组中不包含二进制元素,那么就能成功的解包。

haodiao avatar Nov 08 '25 18:11 haodiao