面试题答案
一键面试网络延迟问题
- 多次网络请求开销:使用
SETNX
命令设置锁,再搭配EXPIRE
命令设置过期时间,这需要两次网络请求。每次网络请求都存在一定的延迟,在高并发场景下,多次网络请求带来的延迟累积可能会严重影响系统性能。如果 Redis 服务器与应用服务器网络状况不佳,如存在丢包、带宽不足等情况,这种延迟对性能的影响会更加明显。 - 原子性受影响:由于是两次命令操作,理论上在
SETNX
成功后、EXPIRE
执行前,可能会出现程序崩溃等异常情况,导致锁没有设置过期时间,从而出现死锁。虽然可以通过使用 Lua 脚本来保证这两个操作的原子性,但这又引入了额外的网络开销,因为需要将 Lua 脚本发送到 Redis 服务器执行。
锁竞争问题
- 大量请求等待:在高并发场景下,当多个客户端同时尝试获取锁时,只有一个客户端能成功获取锁,其他客户端需要不断重试。这些重试操作会占用大量的系统资源,包括 CPU、网络带宽等,导致系统整体性能下降。而且随着并发量的增加,重试次数会急剧上升,进一步加重系统负担。
- 锁的粒度问题:如果锁的粒度设置得过大,例如对整个业务模块加锁,那么在该模块内即使不同操作之间没有实际的资源竞争,也会因为锁的存在而导致并发性能降低。相反,如果锁的粒度设置得过小,又可能会出现并发访问共享资源时的不一致问题,同时也会增加锁的管理开销。
过期时间设置问题
- 过期时间过短:如果设置的过期时间过短,可能会导致业务逻辑还未执行完,锁就已经过期,其他客户端获取到锁并开始执行相同逻辑,从而引发数据不一致等问题。为了避免这种情况,可能需要适当延长过期时间,但这又会降低系统的并发性能,因为在锁被占用的较长时间内,其他客户端都无法获取锁。
- 过期时间过长:设置过长的过期时间,会使得在持有锁的客户端出现异常(如崩溃)时,很长时间内其他客户端都无法获取锁,导致资源长时间被占用,影响系统整体的并发处理能力。同时,过长的过期时间也会增加锁冲突的概率,降低系统性能。
Redis 性能瓶颈
- 单线程模型:Redis 是单线程模型,虽然在处理简单命令时性能很高,但在高并发场景下,大量的锁操作(如
SETNX
和EXPIRE
)会占用 Redis 的处理时间,导致其他命令的处理延迟增加。当系统中存在大量分布式锁操作时,可能会使 Redis 成为整个系统的性能瓶颈。 - 内存使用:如果系统中存在大量的分布式锁,每个锁都需要占用一定的内存空间来存储锁的状态等信息。随着锁数量的增加,Redis 的内存使用量会不断上升,可能会导致 Redis 服务器内存不足,进而影响系统性能,甚至出现 Redis 服务崩溃的情况。