MST

星途 面试题库

面试题:Redis分布式锁唯一标识存储方式及简单查询优化

在Redis分布式锁中,通常有哪些方式来存储唯一标识?如果需要频繁查询锁的状态,怎样对查询操作进行简单优化?
35.5万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试

存储唯一标识的方式

  1. 使用UUID:在客户端生成通用唯一识别码(UUID),将其作为唯一标识存储在Redis中。例如,在Java中可以使用java.util.UUID类生成UUID,然后在获取锁时将其设置为锁的值。
UUID uuid = UUID.randomUUID();
// 获取锁时设置UUID为锁的值
stringRedisTemplate.opsForValue().setIfAbsent(lockKey, uuid.toString());
  1. 时间戳 + 机器ID + 序列号:通过组合当前时间戳、机器ID以及序列号生成唯一标识。时间戳可以保证一定时间范围内的唯一性,机器ID确保不同机器生成的标识不同,序列号用于在同一时间同一机器上生成不同标识。例如,在分布式系统中,每台机器分配一个唯一的机器ID,每次获取锁时,序列号自增。
import time
machine_id = 1
sequence = 0
unique_id = f"{int(time.time())}_{machine_id}_{sequence}"
sequence += 1
# 获取锁时设置unique_id为锁的值
redis.set(lock_key, unique_id, nx=True)

查询操作的优化

  1. 缓存查询结果:对于频繁查询锁状态的操作,可以在应用层缓存查询结果。例如,在Java中使用ConcurrentHashMap缓存锁的状态。每次查询锁状态时,先从缓存中获取,如果缓存中没有再查询Redis。
private static final ConcurrentHashMap<String, Boolean> lockCache = new ConcurrentHashMap<>();

public boolean isLockHeld(String lockKey) {
    Boolean isHeld = lockCache.get(lockKey);
    if (isHeld != null) {
        return isHeld;
    }
    String lockValue = stringRedisTemplate.opsForValue().get(lockKey);
    boolean result = lockValue != null;
    lockCache.put(lockKey, result);
    return result;
}
  1. 使用Redis的发布 - 订阅机制:当锁的状态发生变化时(如锁被释放),通过Redis的发布 - 订阅机制通知相关客户端。这样客户端无需频繁查询Redis来获取锁的最新状态。例如,在Python中:
import redis

r = redis.Redis()
pubsub = r.pubsub()

def subscribe_lock_changes():
    pubsub.subscribe('lock_changes')
    for message in pubsub.listen():
        if message['type'] =='message':
            lock_key = message['data'].decode('utf-8')
            # 处理锁状态变化,如更新本地缓存
            handle_lock_change(lock_key)

def handle_lock_change(lock_key):
    # 例如,清除本地缓存中该锁的状态
    if lock_key in lock_cache:
        del lock_cache[lock_key]