hive.support.concurrency
hive.lock.mapred.only.operation
hive.query.exclusive.lock
hive.lock.numretries
hive.lock.sleep.between.retries
获取锁的代码逻辑
org.apache.hadoop.hive.ql.lockmgr.DbLockManager#lock(org.apache.hadoop.hive.metastore.api.LockRequest, java.lang.String, boolean, java.util.List<org.apache.hadoop.hive.ql.lockmgr.HiveLock>)
while (res.getState() == LockState.WAITING && numRetries++ < maxNumWaits) { backoff(); LOG.debug("Starting retry attempt:#{} to acquire locks for lockId={}. QueryId={}", numRetries, res.getLockid(), queryId); res = txnManager.getMS().checkLock(res.getLockid()); }
// Sleep before we send checkLock again, but do it with a back off // off so we don't sit and hammer the metastore in a tight loop private void backoff() { nextSleep *= 2; if (nextSleep > MAX_SLEEP) nextSleep = MAX_SLEEP; try { Thread.sleep(nextSleep); } catch (InterruptedException e) { } }
这段Java注释描述了一个在重试检查锁(checkLock)操作时采用退避(back off)策略的场景。其含义如下:
Sleep before we send checkLock again: 在再次发送checkLock请求之前,先暂停一段时间。这通常是为了避免在短时间内连续多次请求同一资源,从而减轻系统负担,尤其是对于像元数据存储(metastore)这样的关键服务。
but do it with a back off: 这里提到的“退避”策略是指随着重试次数的增加,等待时间也会逐渐增加。这种策略能够有效防止在遇到暂时性故障时,程序陷入一个紧密的循环中不断尝试,进而过度消耗资源或对服务造成压力。
so we don't sit and hammer the metastore in a tight loop: “坐下来不断敲打元数据存储”形象地表达了如果没有适当的退避策略,程序可能会持续不断地向元数据存储发送请求,就像用锤子不停地敲打一样。这不仅效率低下,还可能导致元数据存储过载,影响其性能和稳定性。
采用退避策略的目的是确保在遇到失败或延迟时,系统能够以一种更加平滑和可控的方式进行重试,避免不必要的资源浪费和系统压力,同时提高系统的整体健壮性和响应能力。