当前位置: 首页 > 科技观察

让Redis变快的4大黑科技,你知道吗?

时间:2023-03-18 22:22:41 科技观察

Redis是一个基于键值对(Key-Value)的NoSQL数据库。Redis的Value可以由String、hash、list、set、zset、Bitmaps、HyperLogLog等数据结构和算法组成。Redis还提供了key过期、发布订阅、事务、Lua脚本、sentinel、Cluster等功能,Redis执行命令的速度非常快,按照官方的表现可以达到10w+的QPS。所以本文主要介绍Redis快的地方,主要有以下几点:开发语言现在我们编程都是用高级语言,比如Java,Python等。也许你觉得C语言很古老,但它确实很有用,毕竟Unix系统是用C实现的。所以C语言是一种非常接近操作系统的语言。Redis是用C语言开发的,所以执行起来会比较快。另外还有一点,大学生学好C,会让你更了解计算机操作系统。不要以为学了高级语言就不用关注底层了。你所欠的债必须偿还。在此推荐一本难读的书《深入理解计算系统》。纯内存访问Redis将所有数据放在内存中,非数据同步正常工作时不需要从磁盘读取数据,0IO。内存中响应时间约为100纳秒,这是Redis速度快的重要基础。先看CPU的速度:以我的电脑为例,主频是3.1G,也就是说每秒可以执行3.1*10^9条指令。所以CPU看世界非常非常慢,内存比它慢一百倍,磁盘比它慢一百万倍。你快吗?借了一张《深入理解计算机系统》的图,展示了典型的内存层次结构。L0层,CPU可以在一个时钟周期访问,基于SRAM的缓存持续时间可以在几个CPU时钟周期访问,然后基于DRAM的主存储器可以在几十到几百个时钟周期访问它们。单线程单线程简化了算法的实现,并发数据结构的实现不仅难度大而且测试起来也麻烦。单线程避免了线程切换和加锁、释放锁带来的消耗。对于服务器端开发,锁和线程切换通常是性能杀手。当然单线程也有缺点,这也是Redis的噩梦:阻塞。如果一条命令执行时间过长,会造成其他命令的阻塞,这对Redis来说是非常致命的,所以Redis是一个针对快速执行场景的数据库。除了Redis,Node.js也是单线程的,Nginx也是单线程的,但都是服务器高性能的典范。非阻塞多通道I/O多路复用机制在这之前先说说传统的阻塞I/O是如何工作的:当使用Read或Write读写一个文件描述符(FileDescriptorFD)时,如果没有收到数据,线程将被挂起,直到接收到数据。阻塞模型虽然简单易懂,但是当需要处理多个客户端任务时,就不会使用它了。I/O多路复用其实就是可以在同一个进程中管理多个连接。多路复用指的是网络连接,多路复用就是同一个线程。在网络服务中,I/O多路复用的作用是将多个连接事件一次性通知给业务代码,处理方式由业务代码决定。在I/O多路复用模型中,最重要的函数调用是I/O多路复用函数,它可以同时监控多个文件描述符(FD)的读写。当部分FD可读/写时,该方法将返回可读/写FD的个数。Redis使用epoll作为I/O多路复用技术的实现,加上Redis自身的事件处理模型将epoll的Read、Write、Close等转换为事件,不会在网络I/O上浪费太多时间。实现对多个FD读写的监控,提高性能。举个形象的例子,比如:一个TCP服务器处理20个客户端套接字。解决方案A:顺序处理。如果第一个Socket因为网卡的原因读取数据慢,阻塞后就会被忽悠。PlanB:每个Socket请求都由一个单独的子进程创建来处理。且不说每个进程都会消耗大量的系统资源,光是进程切换就足以让操作系统疲惫不堪了。C方案:(I/O多路复用模型,epoll):将用户Socket对应的FD注册到epoll中(其实fd_set的数据结构不是Socket的FD而是fd_set之间传递的数据结构)服务器和操作系统),然后epoll只告诉那些需要读/写的Sockets需要处理那些活跃的和变化的SocketFD。这样整个过程只会在调用epoll时阻塞,不会阻塞发送和接收客户端消息。