-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-29479: QuotaCache should always return accurate information #7188
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
HBASE-29479: QuotaCache should always return accurate information #7188
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
// No write throttling | ||
configureLenientThrottle(ThrottleType.ATOMIC_WRITE_SIZE); | ||
refreshQuotas(); | ||
|
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.
These lines shouldn't have been here. Seting a per-user quota of any type shadows the default quotas of all types, making the following assertion fail, if QuotaCache is working properly. The updates to QuotaCache in this PR exposed this test as incorrect.
private QuotaRefresherChore refreshChore; | ||
private boolean stopped = true; | ||
|
||
private final Fetcher<String, UserQuotaState> userQuotaStateFetcher = new Fetcher<>() { |
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.
These Fetcher objects have the same logic as before, but are lifted into top-level-class fields so I can access them in new places.
String user = getQuotaUserName(ugi); | ||
if (!userQuotaCache.containsKey(user)) { | ||
userQuotaCache.put(user, | ||
QuotaUtil.buildDefaultUserQuotaState(rsServices.getConfiguration(), 0L)); | ||
fetch("user", userQuotaCache, userQuotaStateFetcher); | ||
} | ||
return userQuotaCache.get(user); |
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.
This is the meat of the change. If a caller asks for a quota for a given user, check if the quota is already saved in the cache. If so, return it from the cache. If not, do a lookup from the hbase:quota
table, cache the result, and then return it. This means that users of QuotaCache don't need to wait for its chore to run in order to get correct results.
} | ||
|
||
static interface Fetcher<Key, Value> { | ||
Get makeGet(Map.Entry<Key, Value> entry); |
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.
None of the Fetcher implementations used the entry value, so I've stopped passing the a fully Entry
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
When asked for a QuotaLimiter for a given user, the QuotaCache checks if that user's quota state is cached. If it is, it returns a QuotaLimiter based on the cached information. If not, it inserts default quota state into the cache, and returns a default QuotaLimiter. On the next run of the QuotaRefresherChore, it looks in the hbase:quota table for the quota settings for every user in the cache. The consequence of this is: from when the QuotaCache is first asked about a user, until the next run of QuotaRefresherChore, the QuotaLimiters for that user are wrong.
I think it's unacceptable for QuotaCache to return incorrect information. I can see from a code comment that it was implemented this was as a performance optimization, to avoid doing a Get on the quota table in the query handler path. However, the performance consequences of not enforcing quotas can be a lot worse that a few Gets.
In this ticket I'm adding logic to QuotaCache so it immediately fetches quota information for a user from the quota table any time that user is not in its cache.