原因总结

redis作为数据库能拥有如此高的性能具有多方面的原因,本文来探讨其中重要的一部分

  1. 网络I/O:
    • 非阻塞I/O模型: Redis使用非阻塞I/O模型,采用事件驱动的方式进行网络通信。这意味着在一个线程内,可以同时处理多个客户端请求而无需为每个连接创建一个新线程。这提高了并发处理能力。
    • 高效的协议: Redis使用轻量级的文本协议,如RESP(REdis Serialization Protocol),它简单而高效,减少了网络传输的开销。
  2. 磁盘I/O:
    • 内存数据库: Redis主要将数据存储在内存中,减少了对磁盘的频繁读写操作。这使得对数据的访问速度非常快,适用于高速读写的场景。
    • 持久化机制: 尽管主要是内存数据库,但Redis提供了多种持久化机制,如RDB快照和AOF日志文件。这些机制可以根据需求进行配置,以实现数据持久化,同时尽量减小对性能的影响。
  3. 计算速度:
    • 单线程模型: Redis采用单线程模型,通过使用高效的数据结构和算法,提高了在单个线程上的计算速度。这对于简单的操作和高并发场景是非常有效的。
  4. 数据结构:
    • 优化的数据结构: Redis提供了丰富的数据结构,如字符串、哈希表、有序集合等。这些数据结构在实现上经过了优化,使得它们在各自的应用场景下能够高效地执行相关操作。
    • 内部编码: Redis对不同类型的值采用了不同的内部编码方式,例如压缩列表、哈希表、跳跃表等,以提高存储效率。
  5. 多路复用:
    • 事件驱动和多路复用: Redis使用事件驱动的模型,通过多路复用技术(如epollkqueue等)来处理多个客户端连接。这允许Redis在单个线程上同时监听多个套接字,提高了并发连接的处理能力。
  6. Pipeline 操作:
    • 批量操作: Redis支持Pipeline操作,可以将多个命令打包一次性发送到服务器执行,减少了往返时间。这对于需要执行大量命令的场景,如批量读取或写入,能够显著提高性能。
  7. 分布式架构:
    • 分布式部署: Redis支持分布式部署,可以通过分片或集群的方式水平扩展。这意味着可以在多个节点上分布负载,提高整体性能。
  8. 内存管理和优化:
    • 内存碎片整理: Redis通过使用内存池和优秀的内存管理算法,减少了内存碎片的产生,提高了内存利用率。

补充

关于多路复用

io多路复用是五种io模型(阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO)之一

I/O模型

  1. 阻塞 I/O 模型(Blocking I/O):
    • 当一个应用程序发起 I/O 操作时,它会被阻塞,直到操作完成。在此期间,应用程序无法执行其他任务。
    • 适用于简单的同步操作,对于每个操作都等待其完成。
  2. 非阻塞 I/O 模型(Non-blocking I/O):
    • 应用程序发起 I/O 操作后,可以继续执行其他任务而不被阻塞。需要通过轮询或者回调等方式来检查操作是否完成。
    • 适用于需要同时处理多个任务的场景,可以通过轮询或事件通知来实现。
  3. 多路复用 I/O 模型(Multiplexing I/O):
    • 通过一种机制(如selectpollepollkqueue等)同时监听多个 I/O 通道,当任意通道就绪时进行处理。
    • 适用于需要同时处理多个连接的场景,提高了系统的并发性。
  4. 信号驱动 I/O 模型(Signal-driven I/O):
    • 应用程序发起 I/O 操作后,通过信号通知操作的完成。应用程序可以继续执行其他任务。
    • 适用于需要异步通知的场景,但相对较少使用。
  5. 异步 I/O 模型(Asynchronous I/O):
    • 应用程序发起 I/O 操作后,可以继续执行其他任务。当操作完成时,应用程序通过回调或其他方式得到通知。
    • 适用于需要异步处理的场景,能够提高并发和系统的响应性。

下面重点阐述I/O多路复用模型:
非阻塞IO解决了一部分问题,即应用程序发起 I/O 操作后,可以继续执行其他任务而不被阻塞,但是,仍需要进行轮询或者回调等方式来检查操作是否完成。那么有没有可能,当操作完成时再通知应用程序来避免“无用功”呢?

  1. 文件描述符,简称FD,是一个从0 开始的无符号整数,用来关联Linux中的一个文件。在Linux中,一切皆文件,例如常规文件、视频、硬件设备等,当然也包括网络套接字(Socket)。
  2. 当用户去读取数据的时候,不再去直接调用recvfrom(在网络编程中用于接收数据的系统调用)了,而是调用select函数,select函数会将需要监听的数据交给内核,由内核去检查这些数据是否就绪了,如果说这个数据就绪了,就会通知应用程序数据就绪,然后来读取数据,再从内核中把数据拷贝给用户态,完成数据处理,如果N多个FD一个都没处理完,此时就进行等待。
  3. 监听FD的方式、通知的方式又有多种实现,常见的有:select、poll、epoll
  • select和pool相当于是当被监听的数据准备好之后,会把监听的FD整个数据都发送给调用者,需要通过遍历的方式到整个FD中去找哪些是处理好了的文件,所以性能也并不是那么好
  • epoll则相当于内核准备好了之后,会把准备好的数据,直接发给调用者

关于事件驱动

Redis采用单线程的事件驱动模型,而多路复用则是这种模型的一部分,它的核心是通过监听多个套接字(sockets)上的事件,从而在单个线程内同时处理多个客户端的请求。

主要组成部分

  1. 事件处理器(Event Loop):
    • Redis的事件处理器负责监听和分发事件。它通过调用操作系统提供的多路复用函数(如selectpollepollkqueue等)来检测套接字上的事件。
  2. 文件事件(File Events):
    • 文件事件用于处理套接字上的各种事件,例如可读事件、可写事件、连接事件等。在 Redis 中,客户端的命令请求和服务器的响应都是通过文件事件来传递的

工作流程(事件循环)

  1. 监听事件:
    • 事件处理器监听套接字上的事件,包括连接事件、读事件、写事件等。
  2. 等待事件:
    • 事件处理器等待发生事件的通知。这可以通过阻塞调用多路复用函数,或者使用非阻塞I/O模型中的回调函数来实现。
  3. 事件分发:
    • 当套接字上发生事件时,事件处理器将事件分发给相应的事件处理函数。例如,可读事件将触发处理命令请求的函数,可写事件将触发发送响应的函数。
  4. 执行事件处理函数:
    • 事件处理函数执行相应的逻辑,例如处理命令请求、发送响应等。由于采用了非阻塞I/O,一个事件处理函数在执行时不会阻塞其他事件的处理。
  5. 重复:
    • 事件处理器不断重复上述过程,监听、等待、分发、执行,以处理多个套接字上的事件。

优点

  • 高并发: 多路复用使得 Redis 能够在单线程内同时处理大量的客户端连接,提高了并发处理能力。
  • 低延迟: 通过非阻塞I/O和事件驱动模型,Redis可以实现低延迟的请求处理。
  • 资源效率: 单线程的事件处理模型减少了线程切换的开销,提高了资源利用率。

pipeline(Redis管道)

Redis的管道(Pipeline)机制是一种优化技术,用于在客户端与服务器之间批量执行多个命令。通过管道机制,可以减少往返时间,提高性能,尤其是在需要执行大量命令时。

基本原理如下:

  1. 批量发送命令: 客户端可以将多个命令一次性发送给服务器,而不是分开发送。
  2. 一次性获取回复: 服务器接收到命令后,不会立即执行,而是将命令缓存起来。然后一次性执行所有命令,并将结果按照命令发送的顺序一次性返回给客户端。

使用管道机制的好处有:

  • 减少网络往返时间: 因为所有命令都在一次通信中完成,而不是多次单独通信。
  • 提高吞吐量: 在需要执行大量命令时,通过批量操作可以显著提高性能。
    创建管道—>向管道中添加命令—>执行命令并获取结果executePipelined

总结

redis高性能的原因:

  1. 基于内存,计算速度快,减少了对磁盘的频繁读写操作,高速读写
  2. C语言编写,优化的数据结构
  3. 非阻塞IO模型(多路复用),高效简单的协议
  4. 支持分布式架构扩展,搭建高可用集群