
1) 【一句话结论】针对360云安全服务中多个服务共享资源(如API调用次数限制)的高可用场景,推荐采用基于Redis的Redlock算法实现分布式锁,通过多节点部署、原子操作与超时机制,在合理配置下(如节点故障率≤10%、节点数≥5)确保锁的正确性,需结合业务QPS动态调整锁超时时间(如锁超时=1.1×平均请求间隔)。
2) 【原理/概念讲解】分布式锁的核心是保证同一时间仅一个服务访问共享资源。Redlock算法通过多Redis节点(至少5个,假设节点故障率≤10%)实现高可用:
SETNX,设置随机过期时间(避免节点故障导致锁永久占用);3) 【对比与适用场景】
| 方案 | 定义 | 核心特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| Redis Redlock | 基于Redis的分布式锁算法,多节点部署 | 原子操作(SETNX)、超时自动释放、多节点故障容错(故障率≤10%) | 高并发、高可用场景(如API调用次数限制、资源竞争) | 需至少5个Redis节点,锁超时时间需根据业务QPS动态调整 |
| ZooKeeper分布式锁 | 基于ZooKeeper的临时顺序节点 | 临时节点、顺序保证、监听器 | 需强一致性、顺序的场景(如分布式事务协调) | 依赖ZooKeeper集群,性能受ZooKeeper影响,成本较高 |
| 数据库分布式锁 | 通过数据库表记录锁状态 | 事务保证、原子操作(如UPDATE) | 数据库本身支持事务的场景(如数据库本身作为锁存储) | 依赖数据库,故障时锁失效,性能受数据库影响 |
4) 【示例】(伪代码,Redlock实现):
func getRedlockLock(redisNodes []string, lockKey string, lockTTL int) (bool, error) {
n := len(redisNodes)
if n < 5 {
return false, errors.New("至少需要5个Redis节点(假设故障率≤10%)")
}
lockIDs := make([]string, n)
for i, addr := range redisNodes {
client := redis.NewClient(&redis.Options{Addr: addr})
// 尝试设置锁,随机过期时间(避免节点故障导致锁永久占用)
lockID, err := client.SetNX(context.Background(), lockKey, time.Now().UnixNano(), time.Duration(lockTTL)*time.Second).Result()
if err != nil {
client.Close()
return false, err
}
if lockID {
lockIDs[i] = lockID
}
}
// 检查成功获取的锁数量
successCount := 0
for _, id := range lockIDs {
if id != "" {
successCount++
}
}
if successCount < n/2 {
// 释放所有锁(避免锁残留)
for _, id := range lockIDs {
if id != "" {
client.Del(context.Background(), lockKey).Result()
client.Close()
}
}
return false, nil
}
// 锁获取成功,执行业务逻辑(如限制API调用次数)
// ...
// 按顺序反向释放锁(确保所有锁都被正确释放)
for i := len(lockIDs) - 1; i >= 0; i-- {
if lockIDs[i] != "" {
client.Del(context.Background(), lockKey).Result()
client.Close()
}
}
return true, nil
}
5) 【面试口播版答案】(约90秒):
“面试官您好,针对360云安全服务中多个服务共享资源(比如API调用次数限制)的高可用分布式锁设计,我推荐采用基于Redis的Redlock算法。核心思路是通过多节点部署避免单点故障,利用Redis的SETNX命令原子性保证锁的互斥性,结合随机超时机制防止死锁。具体来说,Redlock会向至少5个Redis节点同时请求锁(假设节点故障率≤10%),若成功获取的锁数量超过节点总数的一半(比如5个节点故障2个,仍满足≥3个成功),就认为锁获取成功。业务逻辑执行完毕后,按获取顺序反向释放所有锁。这样即使部分Redis节点故障,只要剩余节点正常,锁机制仍能正常工作。比如,假设我们的API调用次数限制需要控制QPS,锁超时时间可以设置为比业务请求间隔稍长,比如1.1秒(根据QPS计算,比如QPS=1000,锁超时=1.1*1秒),通过压力测试验证锁超时时间是否合适,避免因节点故障导致锁永久占用。”
6) 【追问清单】
7) 【常见坑/雷区】