redis专题:redis面试题汇总

1. redis是单线程的吗?为什么这么快?

答:redis并不是完全单线程。

redis为什么这么快

  • ①:纯内存操作
    • Redis是一个k-v内存数据库,它内部构建了一个哈希表,根据指定的KEY访问时,只需要O(1)的时间复杂度就可以找到对应的数,这些操作都在内存中进行,并不会大量消耗CPU资源,所以速度极快。
  • ②:redis基于epool模型实现的IO多路复用,多路:多个客户端连接,复用:复用一个线程。
    • Redis可以在单线程中监听多个Socket的请求,在任意一个Socket可读/可写时,Redis去读取客户端请求,在内存中操作对应的数据,然后再写回到Socket中。 整个过程非常高效,Redis利用了IO多路复用技术的事件驱动模型,保证在监听多个Socket连接的情况下,只针对有活动的Socket采取反应
  • ③:单线程避免线程切换的开销

redis6.0以前:

        我们常说的redis单线程主要是指Redis的网络IO 和键值对读写是由一个线程来完成的,这也是redis对外提供的存储服务的主要流程。但 Redis 的其他功能,比如持久化、key过期异步删除、集群数据同步等,其实是由额外的线程执行的!

命令执行流程如下:通过socket传输客户端发送的命令,redis单线程从socket中读取命令、经过redis的resp协议解析成redis认识的命令,然后redis执行命令,最后在写回socket,传输给客户端!整个过程是单线程的
在这里插入图片描述

redis6.0以后:

        redis6.0提供了多线程读写io,单最终执行命令的线程依然是单线程的,这样不仅避免了多线程的数据竞争关系,还使io读写更高效!!注意:多线程无法保证命令的执行顺序!!
可以通过如下参数配置多线程

io-threads 4   // 4代表:一个main线程,负责io读写、命令执行;三个io线程,只负责io写
io-threads-do-read yes //开启这个得话,读写都是多线程,但命令执行都是单线程

命令读写流程如下:
在这里插入图片描述

至于redis单线程快的原因是:redis把所有的数据都存储在内存中,所有运算都是内存级别的运算,再者单线程避免了线程切换的性能损耗问题,所以redis是比较快的。正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如 keys *),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。


2. Redis 单线程如何处理那么多的并发客户端连接?

Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
在这里插入图片描述


3. redis管道的作用

管道:客户端可以一次性发送多个请求命令而不用等待服务器的响应,待所有命令都发送完后再一次性读取服务的响应,这样可以极大的降低多条命令执行的网络传输开销!管道执行多条命令的网络开销实际上只相当于一次命令执行的网络开销。

注意:管道并不具备所有命令一起成功的含义,也就是说管道没有原子性!
管道示例:

Pipeline pl = jedis.pipelined();
for (int i = 0; i < 10; i++) {
    pl.incr("pipelineKey");
    pl.set("zhuge" + i, "zhuge");
    //模拟管道报错
    // pl.setbit("zhuge", -1, true);
}
List<Object> results = pl.syncAndReturnAll();
System.out.println(results);


4. redis中Lua脚本的作用

Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。使用脚本的好处如下:

1、减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。使用脚本,减少了网络往返时延。这点跟管道类似。

2、原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。管道不是原子的,不过redis的批量操作命令(类似mset)是原子的。

3、替代redis的事务功能:redis自带的事务功能很鸡肋,报错不支持回滚,而redis的lua脚本几乎实现了常规的事务功能,支持报错回滚操作,官方推荐如果要使用redis的事务功能可以用redis lua替代。

注意: 由于Lua脚本是一大批命令在redis中当做一条命令执行,占用着主线程,所以不要在Lua脚本中出现死循环和耗时的运算,否则redis会阻塞,将不接受其他的命令, 所以使用时要注意不能出现死循环、耗时的运算。redis是单进程、单线程执行脚本!

5 单台redis可以抗多少并发?

理论上单台可以抗10w并发,在实际生产中撑死七八万并发!在这种场景下就需要使用redis集群来应对高并发了!但集群不一定完美解决此问题,原因如下:

①:如果多线程操作的是多目标数据,可以使用集群部署,集群完美分摊压力!
②:如果多线程操作的是单目标数据,比如抢购某一件商品库存,由于这件商品的key经过hash运算分配的槽位还是在某一台机器上,所以集群无法分摊并发压力,这个场景的解决方案是:拆分商品的key,让其落在不同的机器上!这样其他机器就能分担压力了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值