在高并发场景下如果只用一把互斥锁会出现哪些问题?
- 同一时间只能有一个请求占用,如果是大量的并发上来,性能是会急剧下降的,所有的请求都得加锁比如如果数据没有进行任何修改的话,是不需要加锁的。
- 如果读数据的请求还没读完,这个时候来了一个写请求,这个时候是不能写数据的,不然数据就不正确了,要等到前面读锁全部释放掉以后,写请求才能执行,所以需要给这个读请求加一个标识(读锁),让写请求知道,这个时候是不能修改数据的,不然数据就不一致了。
- 如果已经有人在写数据了,再来一个请求写数据,也是不允许的,这样也会导致数据的不一致,所以所有的写请求,都需要加一个写锁,是为了避免同时对共享数据进行写操作。
Redisson给我们提供了读写锁机制,我们可以用读写锁在保证数据并发安全同时优化我们热点key的读写效率
@GetMapping("/readHotKeyValue")
@ResponseBody
public String readHotKeyValue() {
RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");
String s = "";
RLock rLock = readWriteLock.readLock();
try {
rLock.lock();
s = stringRedisTemplate.opsForValue().get("myhotkey");
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
}
return s;
}
@PostMapping("/writeHotKeyValue")
@ResponseBody
public boolean writeHotKeyValue() {
RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");
boolean result = true;
String s = "";
RLock wLock = readWriteLock.writeLock();
try {
wLock.lock();
s = UUID.randomUUID().toString();
stringRedisTemplate.opsForValue().set("myHotKey", s);
} catch (InterruptedException e) {
result = false;
e.printStackTrace();
} finally {
wLock.unlock();
}
return result;
}
- 读 + 读: 相当于无锁,并发读,只会在redis中记录好,所有当前的读锁,他们都会同时加锁成功
- 写 + 读: 等待写锁释放
- 写 + 写: 阻塞方式
- 读 + 写: 有读锁,写也需要等待
总之:只要有写的存在,都必须等待