标签 Redis 下的文章

原文来源:脉脉-Redis 到底是单线程还是多线程?我要吊打面试官!

https://maimai.cn/article/detail?fid=1462427779&efid=1jt-7kkbTGNkYZgeOsFWow&use_rn=1

如有侵权,请在本站留言删除

最近发布的文章,其中有一道题:

Redis是多线程还是单线程?(回答单线程的请回吧,为什么请回,请往下看)

好些粉丝在后台问我:为什么请回,Redis不是单线程吗?

大家注意审题:Redis是多线程还是单线程?

这个问题你要从多个方面回答,如果你仅仅只回答 "单线程" 肯定是说不过去的,为什么呢?

所以今天,栈长利用工作时间紧急把这个问题紧急梳理了下,希望对大家有帮助。

1、Redis 单线程到底指什么?

没错,大家所熟知的 Redis 确实是单线程模型,指的是执行 Redis 命令的核心模块是单线程的,而不是整个 Redis 实例就一个线程,Redis 其他模块还有各自模块的线程的。

下面这个解释比较好:

Redis配图 (1).png

Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。

因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。

参考:http://www.jianshu.com/p/6264fa82ac33

2、Redis 不仅仅是单线程

一般来说 Redis 的瓶颈并不在 CPU,而在内存和网络。如果要使用 CPU 多核,可以搭建多个 Redis 实例来解决。

其实,Redis 4.0 开始就有多线程的概念了,比如 Redis 通过多线程方式在后台删除对象、以及通过 Redis 模块实现的阻塞命令等。

来源官方的解释:

Redis配图 (2).png

如果你能说到这里,对 Redis 单/多线程的理解也有你自己更多的认识了。

另外,前些天 Redis 6 正式发布了,其中有一个是被说了很久的多线程IO:
Redis配图 (3).png

这个 Theaded IO 指的是在网络 IO 处理方面上了多线程,如网络数据的读写和协议解析等,需要注意的是,执行命令的核心模块还是单线程的。

所以,你要是再把 Redis 6.0 网络处理多线程这块回答上了,你也不至于 "请回" 了。

之前有的人在后台和我杠精说:Redis 6 不是还没发布吗?

Redis 6 Beta 版本多线程这个说了多久了,作为一个程序员,如果这个还不能 get 到的话,那就有点 OUT 了,如果确实没听说还好,如果听说了,还要和我杠精,我就无言以对了,对于新技术的发展和学习不就是我们和面试官的谈资吗?!

3、为什么网络处理要引入多线程?

之前的段落说了,Redis 的瓶颈并不在 CPU,而在内存和网络。

内存不够的话,可以加内存或者做数据结构优化和其他优化等,但网络的性能优化才是大头,网络 IO 的读写在 Redis 整个执行期间占用了大部分的 CPU 时间,如果把网络处理这部分做成多线程处理方式,那对整个 Redis 的性能会有很大的提升。

网上也有对 Redis 单/多线程情况下的 get/set 操作性能做了对比:

Redis配图 (4).png

Redis配图 (5).png

参考:blog.csdn.net/weixin_45583158/article/details/100143587

从上面的性能测试图来看,多线程的性能几乎是单线程的两倍了,从该文章来看,这个只是简单的针对多线程性能的验证,并没有做很多严谨的测试,不能作为线上指标参考。

但可以知道的是,Redis 在网络处理方面上了多线程确实会让 Redis 性能上一个新台阶,不过 Redis 6.0 刚发布,不可能有企业马上上生产环境,可能还需要一段时间的优化和验证,我们再期待吧。

最后,目前最新的 6.0 版本中,IO 多线程处理模式默认是不开启的,需要去配置文件中开启并配置线程数,有兴趣的研究下吧。

总结

这篇文章只是对 Redis 单线程/多线程有个基本的认识和总结,吊打面试官可能还说不上,但是在面对面试官提问的时候,不要只是单纯的说单线程,你要回答的还要比这个更多。

一些面试题 P1

写这玩意的初衷:

刚好写这段文章的时候正在面试,但是面试的时候发现对一些问题回答的不够规范,在此感谢其中一家公司的HR建议,对此重新写一下个人对于面试题的解析.

1.Redis-什么是缓存穿透?

[适用于高速缓存系统回答(也许)]

我们先来描述一下含有Redis时用户访问场景:

有缓存:用户请求-》查询Redis是否有缓存-》有-》从Redis返回数据-》处理数据-》返回用户

无缓存:用户请求-》查询Redis是否有缓存-》无-》请求MYSQL-》处理MYSQL数据-》写入Redis缓存-》-》返回用户

Redis本身就是对于高并发的数据读取来缓解MYSQL 的I/O查询过慢 ,缓存穿透就是当用户访问网站的时候,查询高速缓冲数据库中是否有数据,当太多用户刚好都访问没有中标Redis数据时,就会都去查询持久性数据库(也就MYSQL类型),这会给持久性数据库的造成过大的压力。

简要的说,就是查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询。这会给持久性数据库的造成过大的压力。

2.Redis-什么是缓存击穿?

而击穿就会有点不同了,这种情况就是有一个很火的Key,例如首页,微博热点什么的,但是刚好Key失效或者太多人Redis直接干崩溃了,那么用户就穿过Redis,全部都去查询持久性数据库,但这个时候本身就是热点Key很容易就会把持久性数据库打到崩溃。这就是击穿

3.针对上述问题如何解决?

缓存穿透

  1. 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;(因为非法的访问根本就不用理)
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。

缓存击穿

  1. 热点Key直接设置为永远不过期,有数据直接刷新value不用,理过期时间
  2. 添加排斥锁,假设如果有一个人进行查询时,顺带上锁,其他人检查到锁的时候,等待10s后重新从Redis中获取即可
  3. 部署集群Redis,就算打到一个Redis还有千千万万的Redis服务

4.epoll与select有什么区别?

epoll 和 select 都是 I/O 多路复用的技术,都可以实现同时监听多个 I/O 事件的状态。

epoll 相比 select 效率更高,主要是基于其操作系统支持的I/O事件通知机制,而 select 是基于轮询机制。

来源:张朋

5.单机redis与集群redis?

单机Redis会有可能会很容易导致内存和CPU的能力上限。

集群Redis可以分担单机的缓解压力减少穿透、击穿情况,由于Redis主从复制架构每个数据库都要保存整个集群中的所有数据,容易形成木桶效应,为了最大化利用内存,可以采用集群,就是分布式存储,即每台redis存储不同的内容可

6.为什么memcache只支持kv,而redis支持类型多?

【个人觉得两者是不同方向解决不同环境下的高并发问题,所以我硬原理,我也不清楚】

7.redis数据过期策略是什么?

  1. 定时删除
  2. 惰性删除
  3. 定期删除

8.如何快速定位php程序运行慢的地方?

  1. 装个xdebug,打开profiling, 用cache grind看调度的日志就知道哪是瓶颈了
  2. slow log追踪

9.一个事务里面如果嵌套一个curl操作,会发生什么?

其实这道题,应该是MYSQL事务中进行CURL操作?我觉得应该不会发生太大问题可能主要有这种情况?

try {
    //run startTrans
    //run crul?
    //run commit
} catch (\Throwable $th) {
    //db rollback
}

可能报错什么的?直接回触发cath操作了吧直接回滚了?

同样等待一个大佬回复
  1. curl 如果产生 Fatal error,程序不往下执行,事务交由自动处理程序处理(通常是自动回滚);
  2. curl不产生致命错误,将不影响事务的处理;
  3. 如果在事务中必须使用curl的化,最好设置curl的超时时间,以便主动控制事务回滚。
来源:张朋