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