redis单线程为什么慢

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: redis单线程为什么慢

本文分为以下几个部分说明介绍redis单线程

1.redis为何使用单线程

2.redis使用单线程为何性能那么高

3.redis哪些功能不是单线程

一.redis为何使用单线程

现在的cpu都是多核多线程的架构,理论上程序上开多个线程运行,就代表能有多个线程同时并发的在运行,N个线程运行的总时间等于运行时间最长的任务;单线程运行的总时间是每个任务运行时间之和。

举个例子:

有三个任务

任务 运行时间
任务1 10s
任务2 20s
任务3 15s

单线程执行的总时间:45s   多线程执行的总时间:20s

所以随着运行的线程数增多,系统的吞吐量也会上升。但是实际情况往往是这样:随着线程数的增加,吞吐量是会先上涨,后面,即使再增加线程数,吞吐量也是不会再上涨了,趋于平稳状态。

为什么会这样呢?

多线程运行时,通常都会访问一些共享资源,这些资源同时只能一个线程访问与修改,修改完后才能让别的线程访问,这就导致了多线程并发运行,变成了单线程串行运行,多线程都在排队等待,而且还有上下文切换的开销。这就导致了即使增加再多的线程也无法增加吞吐量。

举个例子:

假如redis是多线程处理请求的,一个线程从list集合LPOP获取元素,需要对集合的长度-1;有另一个线程从list集合LPUSH获取元素,需要对集合的长度+1;两个线程需要对共享资源(集合长度)访问,对共享资源的访问同时只能是一个线程,这样多线程就变成串行操作。

并发编程中,对共享资源的访问都是比较难处理的,如果只是简单的加一个粗粒度的锁来保证,这就会导致性能上不去的情况。

所以采用多线程会导致访问共享资源问题很难处理,而且会导致代码比较复杂,难易维护,所以redis采用了单线程模型。

二.redis使用单线程为何性能那么高

官方数据:redis单线程模型可以达到10Wtps/s。

我觉得redis那么快主要有两个原因:

  1. 数据都存放在内存,高效的数据结构,比如hash列表,通过计算key的hash值就能快速定位到存放位置。
  2. io多路复用的应用,一个线程就可以高效的管理多个连接。

redis的单线程操作是指:网络 IO和键值对读写是由一个线程来完成的,所以下面总结介绍一下阻塞io和非阻塞io的区别。以及非阻塞io在多路复用的应用。

  • 阻塞io

阻塞io模型下,由于调用socket的读写方法都会阻塞,一直等待有对端有数据传输,才会访问,所以一个线程只能处理一条连接,所以需要创建很多个线程来处理连接;这种模式可以由线程池来优化,但是也是治标不治本,因为很多线程其实是空闲不工作的。

  • 非阻塞io

非阻塞的模式下,调用socket的读写方法,如果没有数据可读,就会立即返回,线程可以做其他事情;如果有数据可读,就会从内核把数据拷贝到应用程序,完成数据的获取。

  • 多路复用

在多路复用的模式下,通常是( select/epoll模式  ),对建立好的连接,可以向操作系统订阅可读可写事件,当连接可读写时,操作系统就会发出通知。线程就可以处理这个连接的数据读写。

对redis来说,会向select/epoll注册读写事件和连接建立事件,系统内核一旦监听到有对应的事件发生,就会把事件放到一个队列中,由redis线程获取队列的事件处理,redis根据不同的事件会调用不同的处理器处理。

三.redis哪些功能不是单线程

redis是单线程处理客户端请求的,如果单线程处理的操作是比较耗时的,就会导致客户端的请求没办法处理,所以redis耗时的操作不能由处理客户端请求的线程来处理。

有哪些是耗时的请求呢?

持久化(自动生成RDB,客户端的bgsave命令)、异步删除(客户端异步删除命令)、集群数据同步(主节点和从节点的数据同步)

这些功能,都是主进程fork出子进程来进行操作的,不会影响到客户端请求的正常处理。当然,redis的处理客户端的请求也会存在耗时操作,导致其他客户端的请求无法处理,下节我们来看看redis有哪些耗时的操作,以及怎么优化。

四.总结

我们重点学习了 Redis 关于单线程的三个问题:“Redis 为何使用单线程?”“使用单线程为何性能那么高?”“哪些功能不是单线程?”

现在,我们知道了,Redis 单线程是指它网络 IO和键值对读写都是一个线程完成的,而 采用单线程的一个核心原因是避免多线程开发的访问共享资源的问题。单线程的 Redis 也能获得 高性能,多路复用的 IO 模型+高效的数据结构有密切相关,因为这避免了建立新连接和io读写方法 阻塞问题。

相关实践学习
基于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
相关文章
|
28天前
|
监控 NoSQL 安全
如何在 Redis 中正确使用多线程?
【10月更文挑战第16天】正确使用 Redis 多线程需要综合考虑多个因素,并且需要在实践中不断摸索和总结经验。通过合理的配置和运用,多线程可以为 Redis 带来性能上的提升,同时也要注意避免可能出现的问题,以保障系统的稳定和可靠运行。
37 2
|
28天前
|
存储 NoSQL Redis
Redis 新版本引入多线程的利弊分析
【10月更文挑战第16天】Redis 新版本引入多线程是一个具有挑战性和机遇的改变。虽然多线程带来了一些潜在的问题和挑战,但也为 Redis 提供了进一步提升性能和扩展能力的可能性。在实际应用中,我们需要根据具体的需求和场景,综合评估多线程的利弊,谨慎地选择和使用 Redis 的新版本。同时,Redis 开发者也需要不断努力,优化和完善多线程机制,以提供更加稳定、高效和可靠的 Redis 服务。
33 1
|
2月前
|
消息中间件 存储 NoSQL
剖析 Redis List 消息队列的三种消费线程模型
Redis 列表(List)是一种简单的字符串列表,它的底层实现是一个双向链表。 生产环境,很多公司都将 Redis 列表应用于轻量级消息队列 。这篇文章,我们聊聊如何使用 List 命令实现消息队列的功能以及剖析消费者线程模型 。
98 20
剖析 Redis List 消息队列的三种消费线程模型
|
1月前
|
存储 运维 NoSQL
Redis为什么最开始被设计成单线程而不是多线程
总之,Redis采用单线程设计是基于对系统特性的深刻洞察和权衡的结果。这种设计不仅保持了Redis的高性能,还确保了其代码的简洁性、可维护性以及部署的便捷性,使之成为众多应用场景下的首选数据存储解决方案。
41 1
|
1月前
|
NoSQL Redis 数据库
Redis单线程模型 redis 为什么是单线程?为什么 redis 单线程效率还能那么高,速度还能特别快
本文解释了Redis为什么采用单线程模型,以及为什么Redis单线程模型的效率和速度依然可以非常高,主要原因包括Redis操作主要访问内存、核心操作简单、单线程避免了线程竞争开销,以及使用了IO多路复用机制epoll。
47 0
Redis单线程模型 redis 为什么是单线程?为什么 redis 单线程效率还能那么高,速度还能特别快
|
2月前
|
NoSQL 网络协议 Unix
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
66 1
|
2月前
|
存储 消息中间件 NoSQL
Redis的单线程设计之谜:高性能与简洁并存
Redis的单线程设计之谜:高性能与简洁并存
43 0
|
4月前
|
消息中间件 缓存 NoSQL
Redis快速度特性及为什么支持多线程及应用场景
Redis快速度特性及为什么支持多线程及应用场景
111 11
|
3月前
|
缓存 开发框架 NoSQL
【Azure Redis 缓存】Azure Redis 异常 - 因线程池Busy而产生的Timeout异常问题
【Azure Redis 缓存】Azure Redis 异常 - 因线程池Busy而产生的Timeout异常问题
|
3月前
|
NoSQL 关系型数据库 MySQL
简述redis的单线程模式
简述redis的单线程模式