-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
[improve][broker] Make cursor properties support modify single value concurrently. #17164
[improve][broker] Make cursor properties support modify single value concurrently. #17164
Conversation
e55976f
to
99d89e5
Compare
99d89e5
to
4cce776
Compare
managed-ledger/src/main/java/org/apache/bookkeeper/mledger/ManagedCursor.java
Outdated
Show resolved
Hide resolved
@lhotari Please review again. |
In the description it says: "use a special prefix to prevent internal property loss." |
@lhotari Now, the internal property has not been used, it will first be used to PIP-195. Lines 1221 to 1232 in c1c3c86
pulsar/managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedCursorImpl.java Lines 328 to 338 in 2db3ed5
|
} | ||
}); | ||
|
||
updateCursorPropertiesResultRef.setValue(asyncUpdateCursorProperties(newProperties)); |
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.
the new properties must take effect only after they are persisted to storage.
otherwise:
- in case of failure the value is no consistent on storage
- other readers of the value won't see the value consistently (who reads from this node may see something that will never been read)
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 makes sense, I use a non-reentrant lock instead of AtomicReferenceFieldUpdater
to ensure the new properties take effect after they are persisted to storage. And keep using an asynchronous method.
@Override | ||
public CompletableFuture<Void> setCursorProperties(Map<String, String> cursorProperties) { | ||
private CompletableFuture<Void> asyncReadAndUpdateCursorProperties( | ||
final Function<Map<String, String>, Map<String, String>> updateFunction) { | ||
CompletableFuture<Void> updateCursorPropertiesResult = new CompletableFuture<>(); | ||
ledger.getStore().asyncGetCursorInfo(ledger.getName(), name, new MetaStoreCallback<>() { |
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 we remove the get operation?
Instead, we can only update the local properties cache if we get a BadVersion exception
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.
Instead, we can only update the local properties cache if we get a BadVersion exception
Will this introduce inconsistency between broker memory state and zookeeper storage?
CompletableFuture<Void> updateCursorPropertiesResult = new CompletableFuture<>(); | ||
ledger.getStore().asyncGetCursorInfo(ledger.getName(), name, new MetaStoreCallback<>() { | ||
@Override | ||
public void operationComplete(ManagedCursorInfo info, Stat stat) { | ||
final Map<String, String> newProperties = updateFunction.apply(ManagedCursorImpl.this.cursorProperties); |
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.
Here might introduce a problem, the ManagedCursorImpl.this.cursorProperties
is staled, but we will update the zookeeper with a new stat.
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.
Update the zookeeper with local stat instead of new stat?
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.
We should use the properties from info
.
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.
@Jason918 Maybe we can be removed asyncGetCursorInfo
and cache ManagedCursorInfo
, what do you think?
I removed I'm not sure if I have missed considerations. Please take a look, thanks~ |
4d4d513
to
3da8e12
Compare
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 looks better !
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.
Good work!
managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedCursorImpl.java
Outdated
Show resolved
Hide resolved
6340d80
to
ad83c9d
Compare
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.
Another one is related to this PR.
But it's better to improve it.
The getProperties()
returned a mutable structure, it should be a risk it the properties has been modified outside.
managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedCursorImpl.java
Outdated
Show resolved
Hide resolved
managed-ledger/src/main/java/org/apache/bookkeeper/mledger/util/Futures.java
Outdated
Show resolved
Hide resolved
fff1987
to
292ed62
Compare
managed-ledger/src/main/java/org/apache/bookkeeper/mledger/ManagedCursor.java
Show resolved
Hide resolved
@lhotari Please help review this PR again. |
managed-ledger/src/main/java/org/apache/bookkeeper/mledger/util/Futures.java
Show resolved
Hide resolved
@Override | ||
public void operationComplete(Void result, Stat stat) { | ||
log.info("[{}] Updated ledger cursor: {} properties {}", ledger.getName(), | ||
name, cursorProperties); | ||
ManagedCursorImpl.this.cursorProperties = cursorProperties; | ||
ManagedCursorImpl.this.managedCursorInfo = copy; | ||
ManagedCursorImpl.this.cursorProperties = Collections.unmodifiableMap(newProperties); |
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.
Collections.unmodifiableMap
alone won't make a map immutable if the map gets modified outside of the wrapper. is newProperties
already a copy?
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, the newProperties already a copy, but properties are not copied at setCursorProperties
, I will deal with it in another PR("support internal properties").
Questions added, but no changes requested anymore.
managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedCursorImpl.java
Show resolved
Hide resolved
managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedCursorImpl.java
Show resolved
Hide resolved
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.
The logic LGTM.
…d managedCursorInfo at the same time.
@lhotari Please take the final review. |
Motivation
Currently, the cursor properties only support overall update and it is not thread-safe, but sometimes we need to modify a single value concurrently, such as PIP-195
Modifications
putCursorProperty
/removeCursorProperty
method.stat
before assembly data to ensure data consistency.BadVersionException
has occurred.updateCursorLedgerStat
method to updatecursorLedgerStat
andmanagedCursorInfo
at the same time.Verifying this change
(Please pick either of the following options)
This change is a trivial rework / code cleanup without any test coverage.
(or)
This change is already covered by existing tests, such as (please describe tests).
(or)
This change added tests and can be verified as follows:
(example:)
Does this pull request potentially affect one of the following parts:
If
yes
was chosen, please highlight the changesDocumentation
Check the box below or label this PR directly.
Need to update docs?
doc-required
(Your PR needs to update docs and you will update later)
doc-not-needed
(Please explain why)
doc
(Your PR contains doc changes)
doc-complete
(Docs have been already added)