Redis面试必问知识点
一、Redis只有单线程吗?
Redis 是单线程的,主要是指 Redis 的网络 I/O 线程,以及键值的 SET 和 GET 等读写操作都是由一个线程来完成的。但 Redis 的持久化、集群同步等操作,则是由另外的线程来执行的。
Redis 6.0 版本之后,为了更好地提高 Redis 的性能,新增了多线程 I/O 的读写并发能力
二、Redis采用单线程为什么还那么快?
首先,一个重要的原因是,Redis 的大部分操作都在内存中完成,并且采用了高效的数据结构,比如哈希表和跳表。
其次,因为是单线程模型避免了多线程之间的竞争,省去了多线程切换带来的时间和性能上的开销,而且也不会导致死锁问题。
最后,也是最重要的一点, Redis 采用了 I/O 多路复用机制处理大量的客户端 Socket 请求,这让 Redis 可以高效地进行网络通信,因为基于非阻塞的 I/O 模型,就意味着 I/O 的读写流程不再阻塞。
1、完全基于内存操作
2、C语言实现,优化过得数据结构,基于几种基础的数据结构,Redis做了大量的优化,性能极高
3、使用单线程,无上下文的切换成本
4、基于分阻塞的IO多路复用机制
三、怎么解决缓存并发呢?
首先,客户端发起请求,先从缓存中读取数据,判断是否能从缓存中读取到数据;
如果读取到数据,则直接返回给客户端,流程结束;
如果没有读取到数据,那么就在 Redis 中使用 setNX 方法设置一个状态位,表示这是一种锁定状态;
如果锁定状态设置成功,表示已经锁定成功,这时候请求从数据库中读取数据,然后更新缓存,最后再将数据返回给客户端;
如果锁定状态没有设置成功,表示这个状态位已经被其他请求锁定,此时这个请求会等待一段时间再重新发起数据查询;
再次查询后发现缓存中已经有数据了,那么直接返回数据给客户端。
四、为什么Redis6.0之后有改用多线程呢?
Redis使用多线程并非是完全抛弃单线程,Redis还是使用单线程模型来处理客户端的请求,只是使用多线程来处理数据的读写和协议解析执行命令还是使用单线程
目的:是因为Redis的性能瓶颈在于网络IO而非CPU,使用多线程能提升IO读写的效率,从而整体提高Redis的性能。
五、什么是热key吗?热key问题怎么解决?
所谓热key问题就是,突然有几十万的请求去访问Redis上的某一个特定key,那么这样会造成流量过于集中,达到物理网卡上限,从而导致这台人Redis的服务器宕机引发雪崩
针对热key的解决方案:
- 提前把热key打散到不同的服务器,降低压力
- 加入二级缓存,提前加载热key数据到内存中,如果Redis宕机,就走内存查询
- 缓存击穿
- 加锁更新,比如查询请求A发现缓存中没有,那么对A这个key加锁,同时去数据库查询数据,写入缓存,再返回给用户,这样后面的请求就可以从缓存中拿到数据了。
- 将过期时间组合写在value中,通过异步的方式不断的刷新过期时间,防止此类现象
- 缓存穿透
- 缓存雪崩
- 针对不同key设置不同的过期时间,避免同时过期
- 限流,如果Redis宕机,可以限流,避免同时刻大量请求打崩DB
- 二级缓存,同热key的方案
- volatile-lru:从已设置过期时间的key中,移除最近最少使用的key进行淘汰
- volatile-ttl:从已设置过期时间的key中,移除将要过期的key
- volatile-random:从已设置过期时间的key中随机选择key淘汰
- allkeys-lru:从key中选择最近最少使用的进行淘汰
- allkeys-random:从key中随机选择key进行淘汰
- noeviction:当内存达到阈值的时候,新写入操作报错
- 服务端收到客户端请求,事务以MULTI开始
- 如果客户端正处于事务状态,则会把事务放入队列同时返回给客户端QUEUED,反之则直接执行这个命令
- 当收到客户端EXEC命令时,WATCH命令监视真个事务中的key是否被修改,如果有则返回空回复到客户端表示失败,否则Redis会遍历真个事务队列,执行队列中保存的所有命令,最后返回结果给客户端