Skip to content

HDDS-8195. RDBStore.getUpdatesSince() throws RocksDBException: Requested array size exceeds VM limit#4459

Merged
adoroszlai merged 12 commits into
apache:masterfrom
devmadhuu:HDDS-8195
Mar 28, 2023
Merged

HDDS-8195. RDBStore.getUpdatesSince() throws RocksDBException: Requested array size exceeds VM limit#4459
adoroszlai merged 12 commits into
apache:masterfrom
devmadhuu:HDDS-8195

Conversation

@devmadhuu
Copy link
Copy Markdown
Contributor

Observations about below code in org.apache.hadoop.hdds.utils.db.RDBStore#getUpdatesSince(long, long)

dbUpdatesWrapper.addWriteBatch(result.writeBatch().data(),
result.sequenceNumber());

Above code is in while loop for all log files getting iterated and each log file batch allocates a byte[] array which results in accumulating the data in dbUpdatesWrapper in the form of dataList. This will increase JVM heap due to dataList growing with each allocated byte[] array getting added in dataList for dbUpdatesWrapper object and may further fail to allocate any byte[] array in the log iterator loop on calling "result.writeBatch().data()" code. If Recon has limited heap memory, this may fail frequently and may even fall into worse situation where a first call to "result.writeBatch().data()" may fail to allocate byte[] array and throw "org.rocksdb.RocksDBException: Requested array size exceeds VM limit".

So to reduce the chance of this byte[] array allocation failure, we need to ensure following 3 points:

  1. Recon max memory -Xmx configuration should allocate sufficient heap.
  2. Need to fix and avoid increase in recon heap due to increase in size of dataList wrapped in dbUpdatesWrapper object more than configured limit of default 1 GB. If it crosses more than 1 GB as default, break the loop and wait for delta updates since last sequence number in next periodic task run of delta updates.
  3. Throw RocksDBException to client, so. that Recon client catches the exception and set fullSnapshot as True

https://issues.apache.org/jira/browse/HDDS-8195

Patch was tested locally on docker setup by creating very frequent writes and generated keys using freon tool and waited for recon to get OM DB sync updates.

@devmadhuu
Copy link
Copy Markdown
Contributor Author

@jojochuang @sumitagrawl @dombizita - pls review.

@adoroszlai adoroszlai marked this pull request as draft March 23, 2023 16:45
@adoroszlai
Copy link
Copy Markdown
Contributor

Please create PR only after reasonably clean CI run in fork.

Checkstyle is failing:
https://github.com/devmadhuu/ozone/actions/runs/4503008611/jobs/7925644497#step:6:470

@devmadhuu devmadhuu marked this pull request as ready for review March 23, 2023 17:45
@devmadhuu
Copy link
Copy Markdown
Contributor Author

devmadhuu commented Mar 23, 2023

Please create PR only after reasonably clean CI run in fork.

Checkstyle is failing: https://github.com/devmadhuu/ozone/actions/runs/4503008611/jobs/7925644497#step:6:470

Ran both checkstyle and findbugs locally and all issues fixed. Kindly enable workflows.

Copy link
Copy Markdown
Contributor

@jojochuang jojochuang left a comment

Choose a reason for hiding this comment

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

Look overall good to me. Is it possible to add a test?

public class RDBStore implements DBStore {
private static final Logger LOG =
LoggerFactory.getLogger(RDBStore.class);
public static final int MAX_DB_UPDATES_SIZE_THRESHOLD = 1024 * 1024;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be 1024 * 1024 * 1024?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@jojochuang - Thanks for the review. Yes you are right, I have changed that to 1024 * 1024 * 1024.

@devmadhuu
Copy link
Copy Markdown
Contributor Author

Thanks, I ran existing test cases of delta OM DB snapshots and covering the feature. They ran fine. If you are looking for any specific coverage of any usecase, please let me know.

Copy link
Copy Markdown
Contributor

@sumitagrawl sumitagrawl left a comment

Choose a reason for hiding this comment

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

@devmadhuu thanks for working over this, LGTM. UT case related to the scenario can be added, like crossing limit of sequence log file size

Copy link
Copy Markdown
Contributor

@jojochuang jojochuang left a comment

Choose a reason for hiding this comment

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

The code looks good to me. But it involves a few moving parts and a test is really needed to ensure different components respond properly, for example, does recon respond to OM properly when the DB update is not successful.

@devmadhuu
Copy link
Copy Markdown
Contributor Author

@sumitagrawl Thanks for the review. Additional UT and assertions have been updated. Pls re-review.

@devmadhuu
Copy link
Copy Markdown
Contributor Author

The code looks good to me. But it involves a few moving parts and a test is really needed to ensure different components respond properly, for example, does recon respond to OM properly when the DB update is not successful.

@jojochuang - Thanks for the review. Additional UT and assertions have been updated. Pls re-review.

@adoroszlai adoroszlai requested review from jojochuang and sumitagrawl and removed request for sumitagrawl March 28, 2023 08:16
Copy link
Copy Markdown
Contributor

@sumitagrawl sumitagrawl left a comment

Choose a reason for hiding this comment

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

@devmadhuu Please handle one of minor comment

this(dbFile, options, new ManagedWriteOptions(), families,
new CodecRegistry(), false, 1000, null, false,
TimeUnit.DAYS.toMillis(1), TimeUnit.HOURS.toMillis(1));
this.maxDbUpdatesSizeThreshold = MAX_DB_UPDATES_SIZE_THRESHOLD;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

plz use common default value, do not use another default value 80 which will create confusion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@sumitagrawl - I have handled this comment. Pls re-review.

Comment on lines 95 to 110
@SuppressWarnings("checkstyle:ParameterNumber")
@VisibleForTesting
public RDBStore(File dbFile, ManagedDBOptions rocksDBOption,
ManagedWriteOptions writeOptions,
Set<TableConfig> tableConfigs, CodecRegistry registry,
boolean openReadOnly, int maxFSSnapshots,
String dbJmxBeanNameName, boolean enableCompactionLog,
long maxTimeAllowedForSnapshotInDag,
long pruneCompactionDagDaemonRunInterval,
long maxDbUpdatesSizeThreshold) throws IOException {
this(dbFile, rocksDBOption, writeOptions, tableConfigs, registry,
openReadOnly, maxFSSnapshots, dbJmxBeanNameName,
enableCompactionLog, maxTimeAllowedForSnapshotInDag,
pruneCompactionDagDaemonRunInterval);
this.maxDbUpdatesSizeThreshold = maxDbUpdatesSizeThreshold;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add the new param to the existing constructor instead of creating a new one.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@adoroszlai - I have handled this review comment. Pls re-review.

LOG.info("Number of updates received from OM : {}, " +
"SequenceNumber diff: {}, SequenceNumber Lag from OM {}.",
numUpdates, getCurrentOMDBSequenceNumber() - fromSequenceNumber, lag);
return null != dbUpdates ? dbUpdates.isDBUpdateSuccess() : false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
return null != dbUpdates ? dbUpdates.isDBUpdateSuccess() : false;
return null != dbUpdates && dbUpdates.isDBUpdateSuccess();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@adoroszlai - I have handled this suggestion. Pls re-review.

Copy link
Copy Markdown
Contributor

@jojochuang jojochuang left a comment

Choose a reason for hiding this comment

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

LGTM from me

@adoroszlai adoroszlai merged commit 2a82613 into apache:master Mar 28, 2023
@adoroszlai
Copy link
Copy Markdown
Contributor

Thanks @devmadhuu for the patch, @jojochuang, @sumitagrawl for the review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants