为什么Redis是单线程的?为什么Redis这么快!
Java相关面试经常会问到缓存的问题。更基础的会问“80/20规则”和“冷热数据”。比较困难的会询问缓存雪崩和缓存命中。 、缓存预擦除、缓存更新、缓存下载等问题。这些看似不寻常的想法都与我们的缓存服务器有关。常用的缓存服务器有Redis、Memcached等,笔者目前只使用Redis。有点儿。
如果你从未见过在之前采访中问你《为什么说Redis是单线程的以及Redis为什么这么快!》的面试官,读完这篇文章你应该感到幸运!如果你恰好是高面试官,你也可以用这个问题来和你的对手朋友“看水”来测试一下他的技能。
好吧!进入正题吧!我们先讨论Redis是什么,为什么Redis这么快,然后讨论为什么Redis是单线程的?
2。 Redis简介
Redis是一个开源的内存数据存储系统。可用作:数据库、缓存和消息中间件。
它支持多种类型的数据结构,例如 Strings、Hash、List、Set、Sorted Set 或 ZSet、范围查询以及 Bitmaps、Hyperlogs 和地理空间索引半径查询。 五种常见的数据结构类型是:String、List、Set、Hash 和 ZSet。
Redis 内置复制、LUA 脚本、LRU 驱逐、交换和各种级别的磁盘持久化,并使用 Redis Sentinel 和自动分区(Cluster)来提供高可用性(High Availability)。
Redis 提供了持久化选项,允许用户将数据存储在磁盘上进行存储。根据实际情况,可以按照一定的时间间隔将数据导出到磁盘(镜像),也可以添加到命令行(仅添加AOF文件)。当执行写命令时,会将写入的命令复制到硬盘上。 。您还可以禁用持久性并将 Redis 用作高效的网络缓存数据实用程序。
Redis 不使用表,其数据不会预先确定或强制用户连接 Redis 中存储的不同数据。
数据存储方式按存储方式可分为:硬盘数据和内存数据。 Redis 将数据存储在内存中。读写数据时不受硬盘I/O速度的限制,因此速度非常快。
(1)硬盘数据操作方法:
(2)内存数据操作方法:
看完上面的描述,对于Redis相关的常见问题有了一点了解,比如如:Redis是什么,Redis常见的数据结构有哪些,Redis有多长等。如果你写,官方提供的数据可以达到100,000+ QPS(每秒查询数)。这个数据库并不比Memcached差,Memcached是一个基于内存的单进程多线程的KV数据库!有兴趣的可以参考官方的benchmark程序测试《How fast is Redis?》(https://redis.io/topics/benchmarks)
横轴是连接数,纵轴是QPS 。目前,该图像代表了数量级。希望你在面试的时候能够描述清楚。如果你们的答案顺序有很大不同,请不要问我!
4。为什么 Redis 这么快
1.它完全基于记忆。大多数请求都是纯内存操作,速度非常快。数据存储在内存中,类似于HashMap。 HashMap的优点是查找和操作次数为O(1);
2。数据结构简单,数据操作也简单。 Redis 中的数据结构是专门为以下目的而设计的:
3。使用单个线程可以避免不必要的状态更改和竞争条件。不存在多进程或多线程造成的重叠消耗CPU。无需考虑各种锁问题,也无需添加Lock释放锁操作,没有可能出现的死锁带来的显示消耗;
4。采用多路I/O复用模型,不阻塞IO;
5。使用不同的基本模型,它们之间的基本模型是与客户通信的应用方法和应用协议不同。 Redis直接构建VM机制,因为一般系统调用系统函数的话,传输和请求花费的时间会更少;
以上概念都比较容易理解。下面简单讨论一下多路I/O复用模型:
(1) 多路I/O复用模型
多路I/O复用模型分别使用select、poll、epoll -monitor I /O 同时在多个流上进行活动。当空闲时,它会阻塞当前线程。当一个或多个流发生I/O事件时,它会从阻塞状态中醒来,因此程序将轮询所有流(epoll只轮询真正发出事件的流),并且该流准备好被处理。这种方法避免了不必要的活动。
这里的“多通道”是指多个网络连接,“复用”是指复用同一个线程。 采用多路I/O复用技术,可以让单个线程高效管理多个连接请求(减少网络IO时间消耗),而且Redis在内存中工作速度很快,这意味着但在内存中的操作不会变成一次影响Redis性能的瓶颈。以上几点成就了Redis的高性能。
5. Redis 为什么是单线程的?
我们首先要明白,上面的分析是为了打造一个Redis速度快的环境! Redis 官方 FAQ 指出,由于 Redis 是基于内存的操作,因此 CPU 并不是 Redis 的瓶颈。 Redis的瓶颈可能是机器内存大小或者网络带宽。由于单线程很容易实现,CPU也不会成为瓶颈,所以实现单线程的方案也就顺理成章了(事实上,使用多线程会带来很多问题!)。
可以查看:https://redis.io/topics/faq
看到这里你可能会哭!我以为会有一个很大的技术点可以让Redis使用单线程很快,但是没想到官方给出的答案似乎是在欺骗我们!不过,我们现在可以清楚地解释为什么Redis这么快了,而且既然单线程已经快了,就没必要再用多线程了!
但是,单核的方式无法利用多核CPU的性能,但是我们可以通过在单机上开启多个Redis实例来改进!
免责声明1:我们在这里接触的唯一线程是处理网络请求时的单个线程。官方Redis Server运行时必须有多个线程,这里有要求请注意!例如,Redis在运行时,会作为子进程或子线程执行(具体是子线程或子进程读者自行考虑);比如我查看了测试服务器上的Redis进程,然后看到进程下有线程:适合SPID一栏。 “SID”列表示线程ID,“CMD”列显示线程名称。
注意事项 2:上图中常见问题解答的最后一段表示从 Redis 4.0 版本开始将支持多线程。然而,多线程仅针对某些事件进行!所以,如果这篇文章在未来的版本中仍然是单线程,读者需要检查一下!
6.注释
1。我们知道Redis采用“单线程复用IO模型”来实现高性能的内存数据库服务。这种机制避免了锁的使用,但同时会降低redis在执行sunion这样的耗时命令时的并发量。因为它是单线程的,所以一次只有一个线程处于活动状态。因此,耗时的命令会导致并发降低,不仅是读并发,还有写并发。单个线程只能使用一个CPU核心,因此可以在同一个多核服务器上启动多个实例,以创建主-主或主-从。耗时的读取命令可以完全在从机上执行。
需要更改的Redis.conf元素:
pidfile /var/run/redis/redis_6377.pid #pidfile要加上端口号
port 6377 #这个是必须改的
logfile /var/log/redis/redis_6377.log #logfile的名称也加上端口号
dbfilename dump_6377.rdb #rdbfile也加上端口号
2。 “我们不能允许操作系统的平衡,因为我们更了解自己的程序,这样我们就可以在不需要太多CPU的情况下给它们CPU核心,或者让我们的核心进程用另一组步骤来填满。 ”
CPU是影响的重要因素。由于是单线程模型,相对于多核,Redis 更喜欢大缓存和快速 CPU
在多核 CPU 服务器上,取决于 NUMA 配置以及 Redis 性能的位置也是处理器。 。最明显的效果是redis-benchmark使用了随机CPU资源。为了获得准确的结果,您需要使用固定的处理器硬件(在 Linux 上您可以使用任务集)。最有效的方法是将客户端和服务器分离到两个不同的CPU中以使用三级缓存。
7。扩展
以下是您应该了解的几种型号。祝您面试顺利!
1。单进程多线程模型:MySQL、Memcached、Oracle(Windows版);
2。几种型号:Oracle(Linux版);
3。 Nginx有两种进程,一种称为Master进程(类似于管理进程),另一种称为worker进程(真正的进程)。启动方式有两种:
(1)单进程启动:目前系统中只有一个进程,扮演Master进程和worker进程的角色。
(2) 多进程启动:目前系统有1个Master进程,只有1个在工作,至少有1个worker进程在工作。
(3) Master流程主要执行启动和管理全球劳动力的工作;事件处理是在 Workers 中完成的。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。