Redis学习笔记-高性能IO模型&Redis6.0多线程

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis学习笔记-高性能IO模型&Redis6.0多线程

前面的文章简单介绍了 Redis 的底层数据结构,合理地使用底层数据结构可以提升 Redis 读写速度,而 Redis 很快的原因主要有 内存(大部分操作是在内存完成的)、数据结构、IO多路复用机制,这篇文章主要探讨一下 Redis高性能IO模型,为什么单线程 Redis 能每秒处理数十万级的数据,以及 Redis6.0 的多线程解决是什么问题。

1.笔记图


2.Redis 单线程含义


  • Redis 的网络 IO 和键值对读写是由一个线程来完成的
  • Redis 其他功能,如持久化、异步删除、集群数据同步等其实都是由额外线程执行

3.Redis单线程设计

3.1 多线程需要解决的问题

  • 多线程设计合理会增加吞吐量(每秒处理的请求),若设计不良好甚至可能会出现吞吐率下降的情况
  • 系统中通常会存在被多线程共享访问的资源
  • 多线程编程模式面临共享资源并发访问控制问题

3.2 单线程 Redis 为什么那么快?

  • 通常单线程处理能力要比多线程差很多,但 Redis 却能使用单线程模型有每秒处理数十万数据级别的能力
  • Redis 大部分操作是在内存完成的
  • Redis 底层数据结构,如 哈希表、跳表、双向链表
  • 多路复用机制

4.多路复用机制

       Redis 多路复用机制在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率(每秒处理的请求数)。

4.1 IO 模型

  • 监听客户端请求(bind/listen)
  • 和客户端建立连接(accept)
  • 从socket中读取请求(recv)
  • 解析客户端发送请求(parse)
  • 根据请求类型读取键值数据(get)
  • 返回给客户端(send)

4.2 潜在阻塞点

  • accept:当 Redis 监听到一个客户端有连接请求,但一直未能成功建立起连接时,会阻塞其他客户端和 Redis 建立连接
  • recv:当 Redis 通过 recv() 从一个客户端读取数据时,如果一直没有到达,Redis 也会一直阻塞在 recv()

4.3 socket网络模型非阻塞模式

  • socket()方法:socket()方法会返回主动套接字,然后调用 listen() 方法
  • listen()方法:将主动套接字转化为监听套接字,此时可以用来监听来自客户端的连接请求,可设置 accept() 非阻塞模式
  • accept()方法:最后调用 accept() 方法接收到达的客户端连接,并返回连接套接字,可设置 send()/recv() 非阻塞模式

4.4 基于多路复用的高性能 IO 模型 select/epoll

  • 虽然 Redis 线程可以不用继续等待,但是总得有机制继续在监听套接字上等待后续连接请求,并在有请求时通知 Redis
  • 该机制允许内核中同时存在多个监听套接字和已连接套接字
  • Redis 网络框架调用 epoll 机制,让内核监听这些套接字
  • Redis 线程不会阻塞在某一个特定的监听或已连接的套接字上(即不会阻塞在某个请求)
  • 为了在请求到达时能通知到 Redis 线程,select/epoll 提供了事件的回调机制,针对不同事件的发生调用相应的处理函数
  • 避免 Redis 轮询是否有请求,避免造成CPU资源浪费,select/epoll 一旦监测到 FD 上有请求到达时,就会触发相应的事件

5.Redis 6.0 多线程

5.1 使用多线程原因

  • 随着网络硬件的性能提升,Redis 的性能瓶颈有时会出现在网络 IO 的处理上
  • 单个主线程处理网络请求的速度跟不上底层网络硬件的速度

5.2 对应网络 IO 瓶颈方法

  • 用户态网络协议栈(例如 DPDK)取代内核网络协议栈,让网络请求的处理不用在内核里执行,直接在用户态完成处理就行,该方法需要修改网络源码,可能引入新BUG,导致不稳定,该方法没有采用
  • 采用多个IO线程处理网络请求
  • 阶段一:服务端和客户端建立 Socket 连接,并分配处理线程
  • 阶段二:IO 线程读取并解析请求(有多个 IO 线程在并行处理)
  • 阶段三:主线程执行请求操作
  • 阶段四:IO 线程回写 Socket 和主线程清空全局队列

5.3 Redis6.0 多线程开启方式

  • 需要在 redis.conf 中设置 io-thread-do-reads 配置项为 yes,表示启用多线程
  • 需要在 redis.conf 中设置线程个数。一般来说,线程个数要小于 Redis 实例所在机器的 CPU 核个数,例如,对于一个 8 核的机器来说,Redis 官方建议配置 6IO 线程

5.4 优化建议

       如果你在实际应用中,发现 Redis 实例的 CPU 开销不大,吞吐量却没有提升,可以考虑使用 Redis 6.0 的多线程机制,加速网络处理,进而提升实例的吞吐量。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6天前
|
存储 缓存 NoSQL
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(一)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
46 0
|
6天前
|
存储 NoSQL 算法
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(二)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
62 0
|
1天前
|
缓存 NoSQL 中间件
【后端面经】【缓存】36|Redis 单线程:为什么 Redis 用单线程而 Memcached 用多线程?epoll、poll和select + Reactor模式
【5月更文挑战第18天】`epoll`、`poll`和`select`是Linux下多路复用IO的三种方式。`select`需要主动调用检查文件描述符,而`epoll`能实现回调,即使不调用`epoll_wait`也能处理就绪事件。`poll`与`select`类似,但支持更多文件描述符。面试时,重点讲解`epoll`的高效性和`Reactor`模式,该模式包括一个分发器和多个处理器,用于处理连接和读写事件。Redis采用单线程模型结合`epoll`的Reactor模式,确保高性能。在Redis 6.0后引入多线程,但基本原理保持不变。
15 2
|
2天前
|
缓存 NoSQL Redis
【后端面经】【缓存】36|Redis 单线程:为什么 Redis 用单线程而 Memcached 用多线程?--epoll调用和中断
【5月更文挑战第18天】`epoll`包含红黑树和就绪列表,用于高效管理文件描述符。关键系统调用有3个:`epoll_create()`创建epoll结构,`epoll_ctl()`添加/删除/修改文件描述符,`epoll_wait()`获取就绪文件描述符。`epoll_wait()`可设置超时时间(-1阻塞,0立即返回,正数等待指定时间)。当文件描述符满足条件(如数据到达)时,通过中断机制(如网卡或时钟中断)更新就绪列表,唤醒等待的进程。
27 6
|
3天前
|
NoSQL Redis 缓存
【后端面经】【缓存】36|Redis 单线程:为什么 Redis 用单线程而 Memcached 用多线程?
【5月更文挑战第17天】Redis常被称为单线程,但实际上其在处理命令时采用单线程,但在6.0后IO变为多线程。持久化和数据同步等任务由额外线程处理,因此严格来说Redis是多线程的。面试时需理解Redis的IO模型,如epoll和Reactor模式,以及其内存操作带来的高性能。Redis使用epoll进行高效文件描述符管理,实现高性能的网络IO。在讨论Redis与Memcached的线程模型差异时,应强调Redis的单线程模型如何通过内存操作和高效IO实现高性能。
30 7
【后端面经】【缓存】36|Redis 单线程:为什么 Redis 用单线程而 Memcached 用多线程?
|
6天前
|
安全 API 数据库
【转】Android线程模型(AsyncTask的使用)
【转】Android线程模型(AsyncTask的使用)
13 1
|
6天前
|
消息中间件 存储 网络协议
Kafka 线程模型痛点攻克: 提升分区写入 2 倍性能
Apache Kafka的单分区写入性能在某些严格保序场景中至关重要,但其现有线程模型限制了性能发挥。本文分析了Kafka的串行处理模型,包括SocketServer、KafkaChannel、RequestChannel等组件,指出其通过KafkaChannel状态机确保请求顺序处理,导致处理效率低下。AutoMQ提出流水线处理模型,简化KafkaChannel状态机,实现网络解析、校验定序和持久化的阶段间并行化,提高处理效率。测试结果显示,AutoMQ的极限吞吐是Kafka的2倍,P99延迟降低至11ms。
25 3
Kafka 线程模型痛点攻克: 提升分区写入 2 倍性能
|
6天前
|
存储 NoSQL Redis
深入浅出Redis(二):Redis单线程模型与通信流程
深入浅出Redis(二):Redis单线程模型与通信流程
|
6天前
|
NoSQL Redis
Redis 线程模型
Redis 线程模型
|
6天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题