-
Notifications
You must be signed in to change notification settings - Fork 472
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
Implement the new encoding with 64bit size and expire time in milliseconds #1342
Conversation
@PragmaTwice Wow! Awesome feature, especially 64-bit size. |
Awesome, I very need this feature!! |
It is ready for review now. |
src/storage/redis_metadata.h
Outdated
// element size of the key-value | ||
uint64_t size; | ||
|
||
explicit Metadata(RedisType type, bool generate_version = true, bool use_64bit_common_field = true); |
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 a case when we need to pass explicitly the use_64bit_common_field
parameter?
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.
No, we do not need to change this parameter. The old data will be decoded normally, and the new data will be encoded use the new encoding (64bit).
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.
But I am thinking if we set the parameter to false
to allow users rollback to previous kvrocks versions (i.e. users cannot rollback (e.g. to 2.3.0) when they use the new encoding to write some new data to the database, although these old data will be treat as well). Do you have some idea?
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.
Yes, I also had the same idea.
So, maybe we can set 64-bit encoding in the constructor by default, and it will be overwritten by the Decode method in case of decoding from the 'old' format?
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.
maybe we can set 64-bit encoding in the constructor by default, and it will be overwritten by the Decode method in case of decoding from the 'old' format?
Yes, you are right.
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 just thought that the use_64bit_common_field
can be useful in unit tests to test backward compatibility, for example.
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 just thought that the use_64bit_common_field can be useful in unit tests to test backward compatibility, for example.
Good idea.
Co-authored-by: hulk <hulk.website@gmail.com>
@PragmaTwice Hi, I'm trying to add a few unit tests, and the following one is failing:
With the following error:
I'm just wondering is there an error in logic or if my test is somehow incorrect (typo/misunderstanding/etc.) :) |
Hi @torwig, thanks for your testing. In this PR, the This design is aimed to make the code simple. If the |
Co-authored-by: Yaroslav <torwigua@gmail.com>
…ks into new-encoding
@PragmaTwice I see. |
Sure. The logic is in here: |
@PragmaTwice So there is a mistake in my test? |
The correct version is like this: TEST(Metadata, MetadataDecodingBackwardCompatibleSimpleKey) {
auto expire_at = (Util::GetTimeStamp() + 10) * 1000;
Metadata md_old(kRedisString, true, false);
EXPECT_FALSE(md_old.Is64BitEncoded());
md_old.expire = expire_at;
std::string encoded_bytes;
md_old.Encode(&encoded_bytes);
Metadata md_new(kRedisNone, false, true); // decoding existing metadata with 64-bit feature activated
md_new.Decode(encoded_bytes);
EXPECT_FALSE(md_new.Is64BitEncoded());
EXPECT_EQ(md_new.Type(), kRedisString);
EXPECT_EQ(md_new.expire, expire_at);
} You need to use milliseconds for |
@PragmaTwice I intentionally use seconds and explicit |
Your test is added to the codebase, thanks! 558bece |
Co-authored-by: Yaroslav <torwigua@gmail.com>
@PragmaTwice For testing new features I have the following tests, you can add them:
To test backward compatibility, I have the following two ones, but they are failing:
But fixing them by assigning milliseconds instead of seconds won't work because in this case, they would not test backward compatibility anymore. So these two tests can be discarded. |
@torwig Thanks! Added. |
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.
LGTM.
@PragmaTwice Now I realized what was wrong with my failing tests: I set the expiration timestamp in seconds while 64-bit encoding was false, trying to emulate "old" behavior, and PutExpire made a division by 1000, and the result confused me :)
Can some stale versions of kvrocks recognize this format? If user ENABLE it, and find other bug, and revert kvrocks to a old version. Would user get segment fault on these keys? |
Firstly, we currently do not enable this new encoding by default. And if users write some data via the new encoding, they cannot revert their kvrocks version to 2.3.0 or earlier. But if we release 2.4.0 and keep BTW, I think any encoding changes may be a pain to users, which is not specially related to this PR. |
if (generate_version) version = generateVersion(); | ||
} | ||
Metadata::Metadata(RedisType type, bool generate_version, bool use_64bit_common_field) | ||
: flags((use_64bit_common_field ? METADATA_64BIT_ENCODING_MASK : 0) | (METADATA_TYPE_MASK & type)), |
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.
Hi twice, when decoding, should we force get use_64bit
from field?
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.
sure.
@@ -155,6 +158,7 @@ rocksdb::Status Database::TTL(const Slice &user_key, int *ttl) { | |||
Metadata metadata(kRedisNone, false); | |||
metadata.Decode(value); |
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.
When Decode happens here, would it have the right data when a 32bit size instance read 64bits data?
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.
Sure. You can read the implementation of Decode
.
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.
oops, seems Decode
reset it flags rather than default argument. Seems ok to me
It closes #1033.
See proposal in #1033, after this change, these old data can still be readable/writable, but all new data will be written via the new encoding.
NOTE: although the encoding now support 64bit size, maybe some place in code still use
int32_t
/int
so it cannot work well in large number of items more than 32bit. We can fix them after this PR.After some discussion, we create a new build option ENABLE_NEW_ENCODING (currently default OFF), and users need to turn this option on to use this feature.