Redis 分布式锁设计 —— 两个编码规范
系列 - 分布式锁设计与实现
目录
记录两个在编码过程中应该注意的编码规范,作为今后的编码原则。
1 不要生吞异常
Unlock 发送请求,如果发生 Socket 异常导致逻辑上解锁但实际上未解锁,是否需要将异常抛出?
- 若不处理异常,Redis 中的 Key 会在设定的 30s 后过期,过期后可以将其与解锁看做等效,因此可以不处理异常;
- 若需要处理异常,则将该异常抛出,用户在使用 Unlock 时需要处理该异常。
原则:不要在代码中假设某种异常不会发生,或者忽略某中异常是无所谓的。
如果不将异常抛出或没有输出到日志,程序在出现莫名其妙的异常后会难以定位问题。因此不要忽略异常。
2 区分“判断”与“校验”
在代码中,如果只有满足某种条件才能继续向后执行,应该使用校验。如果对于某个条件需要执行不同的分支,应该使用判断。
不要用判断取代校验,这会导致忽略某些异常。
// 校验,将异常抛出
internal void Unlock(string name)
{
if (! (_lockEntries.TryGetValue(name, out var entry) && entry.IsEntered()))
{
throw new InvalidStateException("The local lock is missing or the local lock is not held by the current thread. " +
$"LockName: [{name}]");
}
entry.Exit();
entry.DecRef();
}
// 判断,会忽略异常,不便于今后的问题排查
internal void Unlock(string name)
{
if (_lockEntries.TryGetValue(name, out var entry) && entry.IsEntered())
{
entry.Exit();
entry.DecRef();
}
}