-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Allow realtime get to read from translog #48843
Allow realtime get to read from translog #48843
Conversation
Pinging @elastic/es-distributed (:Distributed/Engine) |
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 (probably best to wait for one other reviewer though ... I understand this one just fine now but side-effects I'd probably miss :))
server/src/main/java/org/elasticsearch/index/fieldvisitor/FieldsVisitor.java
Outdated
Show resolved
Hide resolved
server/src/main/java/org/elasticsearch/index/engine/TranslogLeafReader.java
Show resolved
Hide resolved
…dsVisitor.java more efficient UID decoding Co-Authored-By: Armin Braun <[email protected]>
…ce.java lighter Co-Authored-By: Armin Braun <[email protected]>
…-when-reading-from-translog
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.
Given the number of performance issues I've seen over the past years that were related to refreshes because of GETs, I agree with you that stopping to handle GET requests via the translog was probably a bad idea. We already acknowledged this when re-introducing reads from the translog for updates, I'm good with making all realtime reads use the translog again.
I tried to think about potential sources of inconsistencies and couldn't find any besides of the ones that you already covered.
Drive-by comment: I wonder if we should attempt to also improve the actual get from translog to always succeed, see: I think that this PR together with the PRRL changes to no longer retain additional translog increases the risk of not being able to lookup the operation in translog. Can certainly be done in a follow-up rather than here. |
…GetService.java " This reverts commit ba4971a. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch load-stored-fields-when-reading-from-translog # Changes to be committed: # modified: server/src/main/java/org/elasticsearch/index/get/ShardGetService.java #
@elasticmachine run elasticsearch-ci/packaging-sample-matrix
I thought a bit about this before pushing this change, and came to the conclusion that it will not matter in practice. Even with peer recovery retention leases now allowing quicker clean-up of translog, this is very unlikely to happen:
Triggering an internal refresh in the remaining edge cases does not sound too bad to me. I can look into what it would take to never fall back to a refresh, but the added complexity might not be worth adding more code to deal with this. |
The realtime GET API currently has erratic performance in case where a document is accessed that has just been indexed but not refreshed yet, as the implementation will currently force an internal refresh in that case. Refreshing can be an expensive operation, and also will block the thread that executes the GET operation, blocking other GETs to be processed. In case of frequent access of recently indexed documents, this can lead to a refresh storm and terrible GET performance. While older versions of Elasticsearch (2.x and older) did not trigger refreshes and instead opted to read from the translog in case of realtime GET API or update API, this was removed in 5.0 (#20102) to avoid inconsistencies between values that were returned from the translog and those returned by the index. This was partially reverted in 6.3 (#29264) to allow _update and upsert to read from the translog again as it was easier to guarantee consistency for these, and also brought back more predictable performance characteristics of this API. Calls to the realtime GET API, however, would still always do a refresh if necessary to return consistent results. This means that users that were calling realtime GET APIs to coordinate updates on client side (realtime GET + CAS for conditional index of updated doc) would still see very erratic performance. This PR (together with #48707) resolves the inconsistencies between reading from translog and index. In particular it fixes the inconsistencies that happen when requesting stored fields, which were not available when reading from translog. In case where stored fields are requested, this PR will reparse the _source from the translog and derive the stored fields to be returned. With this, it changes the realtime GET API to allow reading from the translog again, avoid refresh storms and blocking the GET threadpool, and provide overall much better and predictable performance for this API.
The only place where we created a `Get` is in `PKLookupOperation` and it always passed `true` for both, `realtime` and `readFromTranslog`. That means we can remove the two options and simplifly the handling within `InternalEngine` a bit. Encountered this while looking into elastic/elasticsearch#48843 - a candidate for backport according to #9796 - but turns out it doesn't apply to us, as we already allowed reads from translog. The `source` inconsistency mentioned in one of the issues also doesn't apply - we don't expose includes/excludes for source. (And could follow up on removing the related logic)
The only place where we created a `Get` is in `PKLookupOperation` and it always passed `true` for both, `realtime` and `readFromTranslog`. That means we can remove the two options and simplifly the handling within `InternalEngine` a bit. Encountered this while looking into elastic/elasticsearch#48843 - a candidate for backport according to #9796 - but turns out it doesn't apply to us, as we already allowed reads from translog. The `source` inconsistency mentioned in one of the issues also doesn't apply - we don't expose includes/excludes for source. (And could follow up on removing the related logic)
The realtime GET API currently has erratic performance in case where a document is accessed that has just been indexed but not refreshed yet, as the implementation will currently force an internal refresh in that case. Refreshing can be an expensive operation, and also will block the thread that executes the GET operation, blocking other GETs to be processed. In case of frequent access of recently indexed documents, this can lead to a refresh storm and terrible GET performance.
While older versions of Elasticsearch (2.x and older) did not trigger refreshes and instead opted to read from the translog in case of realtime GET API or update API, this was removed in 5.0 (#20102) to avoid inconsistencies between values that were returned from the translog and those returned by the index. This was partially reverted in 6.3 (#29264) to allow _update and upsert to read from the translog again as it was easier to guarantee consistency for these, and also brought back more predictable performance characteristics of this API. Calls to the realtime GET API, however, would still always do a refresh if necessary to return consistent results. This means that users that were calling realtime GET APIs to coordinate updates on client side (realtime GET + CAS for conditional index of updated doc) would still see very erratic performance.
This PR (together with #48707) resolves the inconsistencies between reading from translog and index. In particular it fixes the inconsistencies that happen when requesting stored fields, which were not available when reading from translog. In case where stored fields are requested, this PR will reparse the _source from the translog and derive the stored fields to be returned. With this, it changes the realtime GET API to allow reading from the translog again, avoid refresh storms and blocking the GET threadpool, and provide overall much better and predictable performance for this API.