Skip to content

Conversation

@marton-bod
Copy link
Collaborator

@marton-bod marton-bod commented Apr 30, 2021

Following up on #2540.
This commit introduces table-level JVM locks for commit operations to avoid requesting HMS locks unnecessarily when multiple threads are trying to commit to the same table concurrently. The implementation uses a lock cache in order to instantiate any new locks in a thread-safe manner and evict table keys over time to avoid caching table keys indefinitely.

@RussellSpitzer @raptond @pvary @aokolnychyi

@github-actions github-actions bot added the hive label Apr 30, 2021
@marton-bod marton-bod changed the title Hive: add table level JVM lock on commit operation Hive: add table level JVM lock on HiveCatalog commit operation Apr 30, 2021
private static synchronized void initTableLevelLockCache(long evictionTimeout) {
if (commitLockCache == null) {
commitLockCache = Caffeine.newBuilder()
.expireAfterAccess(evictionTimeout, TimeUnit.MILLISECONDS)
Copy link
Contributor

Choose a reason for hiding this comment

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

How does expireAfterAccess work?
I am worried about this sequence:

  • C1 commit comes, gets the JVM lock, and HMS lock
  • eviction timeout
  • C2 commit comes, gets a new JVM lock, and tries to lock
  • C1 finishes and unlocks the old JVM lock

Copy link
Collaborator Author

@marton-bod marton-bod Apr 30, 2021

Choose a reason for hiding this comment

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

expireAfterAccess is based on the amount of time that elapsed after the last read/write operation on the cache entry. So the scenario that you mentioned could only happen if the C1 commit takes more than the entire eviction timeout period (10 minutes by default) which is very unlikely. Even if it does happen (e.g. due to some extreme lock starvation), and C2 starts the commit operation, it shouldn't have too much of an impact because the HMS locking mechanism will still enforce that there won't be write conflicts between threads (i.e. we would be basically back to where we are in the status quo, without the table-level locks).

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I like how the worst case scenario in the lock's not working is that we just fall back to the old behavior.

Copy link
Member

@RussellSpitzer RussellSpitzer left a comment

Choose a reason for hiding this comment

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

Thanks so much for this! This is exactly what I was thinking about.

@kbendick
Copy link
Contributor

kbendick commented May 6, 2021

Thanks for making this update. Should we add the new config iceberg.hive.table-level-lock-evict-ms to the docs? Unless a user knows about the concurrent threads issue, this particular config option might be kind of confusing. I'm simply thinking out loud and would be ok with following up with a small docs update in a later PR and/or accepting for the moment that this is likely a more advanced config that most users won't need to update.

@marton-bod
Copy link
Collaborator Author

Thanks @kbendick for reviewing. I also think we probably don't want to include this in the docs in order to avoid overloading users with internally-used configs they'll most likely never need to tune. Tuning this parameter should be very rare and 99% of users would not care about it, I expect. For the remainder of users, they will probably dig into the code anyway and find this flag quite soon after a bit of search, but just my 2 cents.

@aokolnychyi
Copy link
Contributor

Let me also take a look today/tomorrow.

Optional<Long> lockId = Optional.empty();
// getting a process-level lock per table to avoid concurrent commit attempts to the same table from the same
// JVM process, which would result in unnecessary and costly HMS lock acquisition requests
ReentrantLock tableLevelMutex = commitLockCache.get(fullName, t -> new ReentrantLock(true));
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems safe even though one application can interact with multiple metastores as full name includes the catalog name.

Copy link
Contributor

@aokolnychyi aokolnychyi left a comment

Choose a reason for hiding this comment

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

This looks good to me. Users could have maintained that lock outside too but I think it won't harm to prevent such cases in the future.

cc @rdblue @yyanyy @jackye1995

@RussellSpitzer
Copy link
Member

Users can only synchronize entire writes not just the commit process. Without this patch, a user has to do the entire write process synchronously to gain the same effect.

For example instead of two jobs preparing files at the same time and then synchronously committing, a user would need to do one write and commit before proceeding to the next.

@aokolnychyi aokolnychyi merged commit d5443e3 into apache:master May 7, 2021
@aokolnychyi
Copy link
Contributor

Thanks for fixing this, @marton-bod! Thanks for reviewing, @RussellSpitzer @pvary @kbendick!

@kbendick
Copy link
Contributor

kbendick commented May 7, 2021

Thanks @kbendick for reviewing. I also think we probably don't want to include this in the docs in order to avoid overloading users with internally-used configs they'll most likely never need to tune. Tuning this parameter should be very rare and 99% of users would not care about it, I expect. For the remainder of users, they will probably dig into the code anyway and find this flag quite soon after a bit of search, but just my 2 cents.

Yeah that makes sense to me. Only a power user would be likely to tune this parameter and they'd probably go into the code / reach out in one of the channels, etc, like you mentioned. 👍

@marton-bod
Copy link
Collaborator Author

Thanks everyone for the reviews and @aokolnychyi for the merge!

cwsteinbach added a commit to cwsteinbach/apache-iceberg that referenced this pull request Aug 17, 2021
- Add blurbs for apache#2565, apache#2583, and apache#2547.
- Make formatting consistent.
cwsteinbach added a commit that referenced this pull request Aug 19, 2021
* Add 0.12.0 release notes pt 2

* Add more blurbs and fix formatting.

- Add blurbs for #2565, #2583, and #2547.
- Make formatting consistent.

* Add blurb for #2613 Hive Vectorized Reader

* Reword blurbs for #2565 and #2365

* More changes based on review comments

* More updates to the 0.12.0 release notes

* Add blurb for #2232 fix parquet row group filters

* Add blurb for #2308
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants