-
Notifications
You must be signed in to change notification settings - Fork 484
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
feat(hash): Support hash field expiration #2402
base: unstable
Are you sure you want to change the base?
Conversation
As we specified in https://kvrocks.apache.org/community/data-structure-on-rocksdb#encoding-version-and-data-type, the first and second (and maybe more bits from the MSB) of So it should not be used for field expiration. (Also, not all data types need the field expiration feature.) Instead, you can add a new enum value of data type, or add a new field in the metadata of hash. |
@jjz921024 Thanks for your contributions. As @PragmaTwice mentioned, we cannot put the expired flag in the version field and we also need to adopt the SubkeyFilter in compact_filter.cc to recycle expired subkeys. |
@git-hulk Thanks for you reminding. I have added this feature in latest commit. About
I see this issues #2292. Maybe we should finish it first? |
No. It's too ad hoc and will introduce additional maintanance effort. (the encoding of HASH will be inconsistent with other types, which brings huge understanding, maintanance cost and additional code logic) And also, it breaks our whole design of "encoding version", e.g. HASH cannot have encoding version larger than 1. You can consider these options, as I mentioned before.
-1 for this change if no further commits. |
@PragmaTwice Got it, i will change it. |
@ jjz921024 Please let me know if I'm wrong. If the data structure contains at least 1 key that can be expired, we set a special bit to true and later check it. |
Yes. Due to the expiration time is encoded in the field, the time complexity of some commands changes from O(1) to O(n), such as |
@PragmaTwice Hi, I fix it about |
@git-hulk Hi, I had renamed the |
Seems we need to solve the conflict first? |
rebase this pr on the latest commit of unstable branch. |
Seems there are failure in CI. I will check it up |
Quality Gate passedIssues Measures |
@jjz921024 I will take another pass in a few days, thanks for your contribution. |
0704688
to
072c6b1
Compare
@jjz921024 @git-hulk @PragmaTwice I'm looking forward to this feature, is there anything I can help with to help here? |
Thank you for your input. I'll take a look at this weekend. |
rebase this branch on the HEAD |
src/storage/redis_db.cc
Outdated
// if type is hash, we still need to check if the all of fields expired. | ||
if (metadata->Type() == kRedisHash) { | ||
HashMetadata hash_metadata(false); | ||
s = hash_metadata.Decode(*raw_value); | ||
if (!s.ok()) return s; | ||
redis::Hash hash_db(storage_, namespace_); | ||
if (!hash_db.ExistValidField(ctx, ns_key, hash_metadata)) { | ||
return rocksdb::Status::NotFound("no element found"); | ||
} | ||
} |
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.
This will make almost all operation of HASH inefficient, we should consider how to do this in another way.
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 requires at least O(N) IO accesses for every HASH operation. And if you think about it: not all operations require to check that all elements are expired before the actual operation.
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 seems that only hset
and hmset
does not need to check the expire of the field?But we don't know the the command type in the GetMetadata()
Awesome work, @jjz921024 Maybe we need some benchmark - before include this feature and after? Тo test the impact of new logic on basic HSET's command (and prevent or minimize it)? |
@git-hulk @ltagliamonte Hi, I don't know how to commit code on the new pr #2717 , so I just keep working here. For the first point you mentioned on #2717 (comment), I had finish. please review. And the second point, do you mean that the
|
@aleksraiden Hi, After optimization of 473db0c, the expire fields should have no effect on HSET command. Should we add some bench test for read command of hash type (like hgetall)? |
I have a test by standard redis-bench yesterday (before your commit) - and at quick look is there NO any impact to performance. But standard test looks only to GET/HSET as I see. Great job! |
@jjz921024 Perhaps you can suggest your change in the new PR due to this PR is overload for discussing. What do you think?
@aleksraiden Great! |
I'm pleasure to do it and I will try my best to finish this feature if i can. |
@jjz921024 Thank you! We will take care of PR #2717 to keep the original commit information while merging. |
This pr want to close #2269
Encoding
To implement hash expiration by field level, we encode the expiration time into the first 8 bytes of value.
For example:
And we use the second bit of the flags in metadata to indicate whether encode the expiration into value.
If all the fields in the hash have no encode expiration time, the
flags
will be1 0 0 0 | 0 0 1 0
.If any field in the hash is encoded into the expiration time, the
flags
will be1 1 0 0 | 0 0 1 0
.Flags conversion
For the HEXPIRE command, it will set an expiration on one or more fields.
If we execute hexpire command on a hash key that has not been set to expire, this will set the secode bit of
flags
and encode expiration for all fields (fields that not appear in the command will be set to 0)Add commands
According to https://redis.io/docs/latest/commands add a series of related commands:
HEXPIRE
,HPEXPIRE
,HEXPIREAT
,HPEXPIREAT
HEXPIRETIME
,HPEXPIRETIME
,HTTL
,HPTTL
HPERSIST