Skip to content
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

Fail force-merges on read-only engines #64756

Merged
merged 12 commits into from
Dec 17, 2020

Conversation

howardhuanghua
Copy link
Contributor

@howardhuanghua howardhuanghua commented Nov 9, 2020

In our customer's production cluster, customer complains that some of the indices cannot do force merge to clean deleted docs.

health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green open  waf_log-2020.08.26              DblUYrcfQA2DsJzUH53QOg 12 0     13555 24101243   2.7gb   2.7gb
green open  waf_log-2020.08.28              mLv9TizPSuSFRwE0Y08vpQ 12 0     23456 30183641  12.7gb  12.7gb
green open  waf_log-2020.08.24              Iej4DBqcQPS7xdF1U6UZcA 12 0     55171 32343532   7.1gb   7.1gb
green open  waf_log-2020.08.23              qI51D1ObRTCNq84UnX9kEQ 12 0     27153 35677246   7.7gb   7.7gb

Here is the output of force merge api call:

POST /waf_log-2020.08.23/_forcemerge?max_num_segments=1&only_expunge_deletes=true&pretty
{
  "_shards" : {
    "total" : 12,
    "successful" : 12,
    "failed" : 0
  }
}

From _cat/segments api, we could see this index has more than one segments in each shard:

GET _cat/segments/waf_log-2020.08.23?v 
index              shard prirep ip            segment generation docs.count docs.deleted    size size.memory committed searchable version compound
waf_log-2020.08.23 0     p      172.16.138.28 _7lh          9845        421      1536889  16.1mb           0 true      false      8.3.0   false
waf_log-2020.08.23 0     p      172.16.138.28 _7lm          9850       1799      1767111    20mb           0 true      false      8.3.0   false
waf_log-2020.08.23 1     p      172.16.138.2  _7lu          9858       2261            0   5.7mb           0 true      false      8.3.0   false
waf_log-2020.08.23 2     p      172.16.138.28 _7h1          9685        547      1453000  15.7mb           0 true      false      8.3.0   false
waf_log-2020.08.23 2     p      172.16.138.28 _7h4          9688       1848      3775021 260.7mb           0 true      false      8.3.0   false
waf_log-2020.08.23 3     p      172.16.138.39 _7kd          9805        489      1601900  17.1mb           0 true      false      8.3.0   false
waf_log-2020.08.23 3     p      172.16.138.39 _7ki          9810       1843      1977995  33.7mb           0 true      false      8.3.0   false

We try to open low level log to check why force merge could not be executed:

PUT /_cluster/settings?pretty
{
  "transient": {
    "logger.org.elasticsearch.index.engine": "trace"
  }
}
'

But we got nothing output about the above index force merge operation. We cost long time to add extra log to figure out that the index has been frozen^^.

Currently even index has write block, we still allow user to execute force merge api, but I think we at least need to add some trace level log to let user know why the merge cannot be executed. So this PR add some useful low level log info to indicate index is read only during refresh, flush and force merge operations.

@DaveCTurner DaveCTurner added :Distributed Indexing/Engine Anything around managing Lucene and the Translog in an open shard. team-discuss labels Nov 9, 2020
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-distributed (:Distributed/Engine)

@elasticmachine elasticmachine added the Team:Distributed (Obsolete) Meta label for distributed team (obsolete). Replaced by Distributed Indexing/Coordination. label Nov 9, 2020
@DaveCTurner
Copy link
Contributor

DaveCTurner commented Nov 9, 2020

A few thoughts:

  • requiring TRACE logging to investigate a user issue is a bug IMO, so I don't think this is the right fix.
  • Read-only engines do support flush and refresh (a no-op is the correct behaviour) so I think no change is required in those two cases. At least the proposed messages are misleading, but really I'd rather not have any message here at all.
  • I don't think we should consider a force-merge to be successful on a read-only engine (at least not unless it would have been a no-op anyway); throwing an exception would indicate its failure to the client which would be much preferable to relying on logs.

Adding the team-discuss label to gather others' thoughts on taking this forward.

@howardhuanghua
Copy link
Contributor Author

howardhuanghua commented Nov 9, 2020

Hi @DaveCTurner , I have updated the PR to support index write block for force merge API instead. Would you please help to review again?
Here is the output of force merge if index has write block:

// my-index-000001 is read only, my-index-000002 is writable
curl -XPOST localhost:9200/my-index-000001,my-index-000002/_forcemerge?pretty
{
  "error" : {
    "root_cause" : [
      {
        "type" : "cluster_block_exception",
        "reason" : "index [my-index-000001] blocked by: [FORBIDDEN/8/index write (api)];"
      }
    ],
    "type" : "cluster_block_exception",
    "reason" : "index [my-index-000001] blocked by: [FORBIDDEN/8/index write (api)];"
  },
  "status" : 403
}

@howardhuanghua howardhuanghua changed the title Add low level log info to indicate read only index blocking operations. Support index write block for force merge API. Nov 9, 2020
@DaveCTurner
Copy link
Contributor

DaveCTurner commented Nov 9, 2020

That doesn't work either, it's fine to force-merge an index that merely has a write block. Indeed ILM applies such a block before force-merging.

Conversely there's no requirement for a frozen index to have a write block. It does by default but you can remove it.

@howardhuanghua
Copy link
Contributor Author

Yes, I could remove the write block for frozen index. I have two questions:

  1. A frozen index uses read only engine internally. Shall we need to set extra write block for it? Before removing write block, indexing doc would be rejected by write block exception. After removing write block, indexing doc would be rejected by read-only engine exception. Is that possible we could use read-only engine exception directly?

  2. Force merge on frozen index (read-only engine) would do nothing (no-op) right? So we could just throw UnsupportedOperationException the same as index/delete operations?

@DaveCTurner
Copy link
Contributor

We discussed this as a team and concluded that simply throwing an unconditional UnsupportedOperationException would be undesirable. For instance if you always force-merge to a single segment before freezing your indices then calling POST _all/_forcemerge?max_num_segments=1 manually should succeed. We saw two possible paths forward:

  • attempt an actual force-merge, but fail it if it tries to write anything on a read-only engine
  • find a rough approximation for whether a force-merge would be a no-op or not and only fail if not

We preferred the second idea: we think it would cover most cases to fail the merge iff the number of segments in the shard was greater than the max_num_segments parameter of the request. I also think there should be some DEBUG logs to describe what's going on.

@howardhuanghua
Copy link
Contributor Author

  • find a rough approximation for whether a force-merge would be a no-op or not and only fail if not

So the rough approximation is that if shard already contains exactly max_num_segments specified number of segments, than we do no-op, if it has more segments than max_num_segments, just fail with UnsupportedOperationException?

@DaveCTurner
Copy link
Contributor

contains exactly max_num_segments

Fewer is ok, otherwise yes that's right.

@howardhuanghua
Copy link
Contributor Author

Hi @DaveCTurner , I have updated the PR, fail force merge if max_num_segments is fewer than current, otherwise do no-op. Would you please help to review?

@DaveCTurner
Copy link
Contributor

@elasticmachine ok to test

@DaveCTurner
Copy link
Contributor

Thanks for merging master @howardhuanghua :) I was just about to ask...

@howardhuanghua
Copy link
Contributor Author

Thank you @DaveCTurner , since TencentCloudES repository is forked from elastic, this PR is merged from TencentCloudES to elastic, so I cannot tick the box to let maintainers push code to the branch. Next time I will branch from elastic repository directly, that would be worked.

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, except for one missing corner case.

@@ -375,6 +375,14 @@ public void flush(boolean force, boolean waitIfOngoing) throws EngineException {
@Override
public void forceMerge(boolean flush, int maxNumSegments, boolean onlyExpungeDeletes,
boolean upgrade, boolean upgradeOnlyAncientSegments, String forceMergeUUID) {
if (maxNumSegments < lastCommittedSegmentInfos.size()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rejects force-merge requests that do not specify the maxNumSegments parameter at all, since that comes through to here as maxNumSegments == ForceMergeSegments.Defaults.MAX_NUM_SEGMENTS == -1. We should accept these requests too, it's ok for them to do nothing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right, I have updated the change.

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @howardhuanghua.

@DaveCTurner DaveCTurner changed the title Support index write block for force merge API. Fail force-merges on read-only engines Dec 17, 2020
@DaveCTurner DaveCTurner merged commit 642b530 into elastic:master Dec 17, 2020
DaveCTurner pushed a commit to DaveCTurner/elasticsearch that referenced this pull request Dec 17, 2020
Today we treat all force-merges on a read-only (e.g. frozen) engine as
no-ops, indicating to the client that they succeeded even if they had no
effect. This commit corrects that behaviour, resolving the resulting
confusion, by rejecting force-merges on read-only engines that are
definitely not no-ops.
DaveCTurner added a commit that referenced this pull request Dec 17, 2020
Today we treat all force-merges on a read-only (e.g. frozen) engine as
no-ops, indicating to the client that they succeeded even if they had no
effect. This commit corrects that behaviour, resolving the resulting
confusion, by rejecting force-merges on read-only engines that are
definitely not no-ops.

Co-authored-by: Howard <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Distributed Indexing/Engine Anything around managing Lucene and the Translog in an open shard. Team:Distributed (Obsolete) Meta label for distributed team (obsolete). Replaced by Distributed Indexing/Coordination. v7.12.0 v8.0.0-alpha1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants