-
Notifications
You must be signed in to change notification settings - Fork 704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new replicate module API to bypass command validation #1357
base: unstable
Are you sure you want to change the base?
Conversation
18763c9
to
c54ba74
Compare
src/valkeymodule.h
Outdated
typedef enum { | ||
VALKEYMODULE_FLAG_DEFAULT = 0, /* Default behavior */ | ||
VALKEYMODULE_FLAG_SKIP_VALIDATION, /* Skip validation */ | ||
} ValkeyModuleFlag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I get some suggestions if this naming is too general
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there benefit set the flag as enum, more flags later? Can we just use int skip (0 for non-skip, 1 for skip) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's always complicated to have types like this in the module API. I believe we support backward and forward compatiblity for modules. I mean, a module built with the valkeymodule.h from Valkey 10 can run on Valkey 9 and vice versa. A module can check if some function exists in the current server by checking if the function is NULL, like if (ValkeyModule_ReplicateWithFlag != NULL) ...
, but to check which flags are valid in an enum, we don't have a way for modules to check that.
I think Wen's suggestion with an int
is simpler, but an even simpler API is to just add ValkeyModule_ReplicateWithoutValidataion
. WDYT?
Internally, we can use an enum or int, but that's doesn't have to be part of the API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think ValkeyModule_ReplicateWithoutValidataion
is also good idea
c54ba74
to
24e6573
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## unstable #1357 +/- ##
============================================
+ Coverage 70.78% 70.90% +0.11%
============================================
Files 120 120
Lines 65046 65071 +25
============================================
+ Hits 46045 46136 +91
+ Misses 19001 18935 -66
|
Open a pr for documentation of this: valkey-io/valkey-doc#192 |
src/valkeymodule.h
Outdated
typedef enum { | ||
VALKEYMODULE_FLAG_DEFAULT = 0, /* Default behavior */ | ||
VALKEYMODULE_FLAG_SKIP_VALIDATION, /* Skip validation */ | ||
} ValkeyModuleFlag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there benefit set the flag as enum, more flags later? Can we just use int skip (0 for non-skip, 1 for skip) ?
src/valkeymodule.h
Outdated
@@ -1092,6 +1097,8 @@ VALKEYMODULE_API int (*ValkeyModule_StringToStreamID)(const ValkeyModuleString * | |||
VALKEYMODULE_API void (*ValkeyModule_AutoMemory)(ValkeyModuleCtx *ctx) VALKEYMODULE_ATTR; | |||
VALKEYMODULE_API int (*ValkeyModule_Replicate)(ValkeyModuleCtx *ctx, const char *cmdname, const char *fmt, ...) | |||
VALKEYMODULE_ATTR; | |||
VALKEYMODULE_API int (*ValkeyModule_ReplicateWithFlag)(ValkeyModuleCtx *ctx, ValkeyModuleFlag flag, const char *cmdname, const char *fmt, ...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ValkeyModuleFlag can be set as int, here we can pass int value;
src/module.c
Outdated
/* Helper function for VM_Replicate and VM_ReplicateWithFlag to replicate the specified command | ||
* and arguments to replicas and AOF, as effect of execution of the calling command implementation. | ||
* Skip command validation if the ValkeyModuleFlag is set to VALKEYMODULE_FLAG_SKIP_VALIDATION. */ | ||
int moduleReplicate(ValkeyModuleCtx *ctx, ValkeyModuleFlag flag, const char *cmdname, const char *fmt, va_list ap) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pls move this function to just above the VM_Replicate, reference the function zsetInitLexRange. It is a helper function too.
The PR comes from a performance issue about current VM_Replicated, then could you pls provide the result how much performance improvement on this PR? |
I don't see notable performance improvement in the multiple tests (1. benchmark 2. CPU utilization, 3. CPU profiling with perf) so I wonder if it is worth introducing this new API. @hwware @hpatro 1. BenchmarkWith validation
Bypass validation
2. CPU utilization
With validation
Bypass validation
3. Performance profiling with
|
@valkey-io/core-team Do you think this is a proper solution? |
I added another CPU utilization test to push around 90% |
46692c8
to
930f8ee
Compare
Signed-off-by: Seungmin Lee <[email protected]>
Signed-off-by: Seungmin Lee <[email protected]>
930f8ee
to
8d71f2c
Compare
Signed-off-by: Seungmin Lee <[email protected]>
fd2cbc0
to
1f41ddd
Compare
New performance test showing performance increase. |
The new module api, if the command does not exist, the server will crash, right? Are we considering adding flags to the client to bypass some checks? For example, a trusted client flag? |
@enjoy-binbin I may be wrong, but I believe the primary can replica anything. The replica receiving it will try to execute it and will fail with an error which is normally just ignored. But there is a config that makes the replica crash:
What do you mean? The module can send stuff to the replication stream even no actually command was sent by any real client. A module is always trusted. A module can do all kinds of dangerous things that can crash the server. |
right, sorry about this confusing wording, i got the context mixed up (reading other discussions at the same time). anyway, what i means is that, can we add flags to the client, or like ctx flags then can bypass some internal checks? i am not sure about it though, i am not that good at module, i am ok with the new module api if needed. |
@valkey-io/core-team can we settle on the |
Issue #1175
Problem
Performance degradation occurs due to the sanity check(lookupCommandByCString) in the VM_Replicate function, which converts const char* into sds and free them for command dictionary lookup. This check is mainly used for debugging purpose, but it is unnecessary for trusted modules. The user seeks a way to bypass this check for performance gains.
Solution
Adding a module API
ReplicateWithoutValidation
allows trusted modules to bypass validation for performance improvements while retaining flexibility for handling failure scenarios on replicas.Test
Unit test
Follow-up work
Valkey document update required: https://valkey.io/topics/modules-api-ref/#section-commands-replication-api