存储唯一标识的方式
- 使用UUID:在客户端生成通用唯一识别码(UUID),将其作为唯一标识存储在Redis中。例如,在Java中可以使用
java.util.UUID
类生成UUID,然后在获取锁时将其设置为锁的值。
UUID uuid = UUID.randomUUID();
// 获取锁时设置UUID为锁的值
stringRedisTemplate.opsForValue().setIfAbsent(lockKey, uuid.toString());
- 时间戳 + 机器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)
查询操作的优化
- 缓存查询结果:对于频繁查询锁状态的操作,可以在应用层缓存查询结果。例如,在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;
}
- 使用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]