搜索
首页数据库RedisRedis使用单线程为什么还这么快

    Redis为什么用单线程?

    多线程的开销

    如果没有良好的系统设计,采用多线程通常会导致如右图所示的结果(注意纵坐标)。刚开始增加线程数时,系统吞吐率会增加,再进一步增加线程时,系统吞吐率就增长迟缓了,甚至还会出现下降的情况。

    Redis使用单线程为什么还这么快

    关键瓶颈在于: 系统中通常会存在会被多线程同时访问的共享资源,为了保证共享资源的正确性,就需要有额外的机制保证线程安全性,例如加锁,这会带来额外的开销。

    比如拿最常用的List类型来举例吧,假设Redis采用多线程设计,有两个线程A和B分别对ListLPUSHLPUSH操作,为了使得每次执行都是相同的结果,即【B线程取出A线程放入的数据】就需要让这两个过程串行执行。这就是多线程编程模式面临的共享资源的并发访问控制问题。

    Redis使用单线程为什么还这么快

    并发访问控制一直是多线程开发中的一个难点问题:如果只是简单地采用一个互斥锁,就会出现即使增加了线程,大部分线程也在等待获取互斥锁,并行变串行,系统吞吐率并没有随着线程的增加而增加。

    同时加入并发访问控制后也会降低系统代码的可读性和可维护性,所以Redis干脆直接采用了单线程模式。

    Redis使用单线程为什么还这么快?

    之所以使用单线程是Redis设计者多方面衡量的结果。

    • Redis的大部分操作在内存上完成

    • 采用了高效的数据结构,例如哈希表和跳表

    • 采用了多路复用机制,使其在网络IO操作中能并发处理大量的客户端请求,实现高吞吐率

    既然Redis使用单线程进行IO,如果线程被阻塞了就无法进行多路复用了,所以不难想象,Redis肯定还针对网络和IO操作的潜在阻塞点进行了设计。

    网络与IO操作的潜在阻塞点

    在网络通信里,服务器为了处理一个Get请求,需要监听客户端请求(bind/listen),和客户端建立连接(accept),从socket中读取请求(recv),解析客户端发送请求(parse),最后给客户端返回结果(send)。

    最基本的一种单线程实现是依次执行上面的操作。

    Redis使用单线程为什么还这么快

    上面标红的accept和recv操作都是潜在的阻塞点:

    • 当Redis监听到有连接请求,但却一直不能成功建立起连接时,就会阻塞在accept()函数这里,其他客户端此时也无法和Redis建立连接

    • 当Redis通过recv()从一个客户端读取数据时,如果数据一直没有到达,也会一直阻塞

    基于多路复用的高性能IO模型

    为了解决IO中的阻塞问题,Redis采用了Linux的IO多路复用机制,该机制允许内核中,同时存在多个监听套接字和已连接套接字(select/epoll)。

    内核会一直监听这些套接字上的连接或数据请求。Redis会处理到达的请求,从而实现了一个线程处理多个IO流的效果。

    Redis使用单线程为什么还这么快

    此时,Redis线程就不会阻塞在某一个特定的客户端请求处理上,所以它可以同时和多个客户端连接并处理请求。

    回调机制

    select/epoll一旦监测到FD上有请求到达时,就会触发相应的事件被放进一个队列里,Redis线程对该事件队列不断进行处理,所以就实现了基于事件的回调。

    例如,Redis会对Accept和Read事件注册acceptget回调函数。当Linux内核监听到有连接请求或读数据请求时,就会触发Accept事件和Read事件,此时,内核就会回调Redis相应的acceptget函数进行处理。

    Redis的性能瓶颈点

    经过上面的分析,虽然通过多路复用机制可以同时监听多个客户端的请求,但Redis仍然有一些性能瓶颈点,这也是我们平时编程需要极力避免的情况。

    1. 耗时操作

    如果任何一个请求在Redis中耗时较长,就会对整个服务器的性能产生影响。后面的请求都要等前面这个耗时请求处理完成,自己才能被处理到。

    这一点需要我们在设计业务场景时去规避;Redis的lazy-free机制也把释放内存的耗时操作放在了异步线程中去执行了。

    2. 高并发场景

    并发量非常大时,单线程读写客户端IO数据存在性能瓶颈,虽然采用IO多路复用机制,但还是只能单线程依次读取客户端的数据,无法利用到CPU多核。

    Redis在6.0可以利用CPU多核多线程读写客户端数据,但只是针对客户端的读写是并行的,每个命令的真正操作还是单线程。

    其他Redis相关的有趣问题

    借此机会也提几个和redis相关的有意思的问题。

    Redis使用单线程为什么还这么快

    • 为什么要用Redis,直接访问内存不好吗?

    这一条其实并没有很明确的界定,对于一些不经常变动的数据,可以直接放到内存里,不一定要放到Redis里,可以放到内存里。在更新数据时可能存在一致性问题,即可能只有某一台服务器上的数据被修改,因此数据仅在本地内存中存在。访问Redis服务器可以解决一致性问题,用Redis的话。

    • 数据太多内存放不下怎么办?比如我要缓存100G的数据,怎么办?

    这里也要打一个广告Tair是淘宝开源的分布式KV缓存系统,它从Redis继承了丰富的操作,理论上总数据量无限制,针对可用性、可扩展性、可靠性也进行了升级,感兴趣的小伙伴们可以了解一下~

    以上是Redis使用单线程为什么还这么快的详细内容。更多信息请关注PHP中文网其他相关文章!

    声明
    本文转载于:亿速云。如有侵权,请联系admin@php.cn删除
    REDIS:流行数据结构指南REDIS:流行数据结构指南Apr 11, 2025 am 12:04 AM

    Redis支持多种数据结构,具体包括:1.字符串(String),适合存储单一值数据;2.列表(List),适用于队列和栈;3.集合(Set),用于存储不重复数据;4.有序集合(SortedSet),适用于排行榜和优先级队列;5.哈希表(Hash),适合存储对象或结构化数据。

    redis计数器怎么实现redis计数器怎么实现Apr 10, 2025 pm 10:21 PM

    Redis计数器是一种使用Redis键值对存储来实现计数操作的机制,包含以下步骤:创建计数器键、增加计数、减少计数、重置计数和获取计数。Redis计数器的优势包括速度快、高并发、持久性和简单易用。它可用于用户访问计数、实时指标跟踪、游戏分数和排名以及订单处理计数等场景。

    redis命令行怎么用redis命令行怎么用Apr 10, 2025 pm 10:18 PM

    使用 Redis 命令行工具 (redis-cli) 可通过以下步骤管理和操作 Redis:连接到服务器,指定地址和端口。使用命令名称和参数向服务器发送命令。使用 HELP 命令查看特定命令的帮助信息。使用 QUIT 命令退出命令行工具。

    redis集群模式怎么搭建redis集群模式怎么搭建Apr 10, 2025 pm 10:15 PM

    Redis集群模式通过分片将Redis实例部署到多个服务器,提高可扩展性和可用性。搭建步骤如下:创建奇数个Redis实例,端口不同;创建3个sentinel实例,监控Redis实例并进行故障转移;配置sentinel配置文件,添加监控Redis实例信息和故障转移设置;配置Redis实例配置文件,启用集群模式并指定集群信息文件路径;创建nodes.conf文件,包含各Redis实例的信息;启动集群,执行create命令创建集群并指定副本数量;登录集群执行CLUSTER INFO命令验证集群状态;使

    redis怎么读取队列redis怎么读取队列Apr 10, 2025 pm 10:12 PM

    要从 Redis 读取队列,需要获取队列名称、使用 LPOP 命令读取元素,并处理空队列。具体步骤如下:获取队列名称:以 "queue:" 前缀命名,如 "queue:my-queue"。使用 LPOP 命令:从队列头部弹出元素并返回其值,如 LPOP queue:my-queue。处理空队列:如果队列为空,LPOP 返回 nil,可先检查队列是否存在再读取元素。

    redis集群zset怎么使用redis集群zset怎么使用Apr 10, 2025 pm 10:09 PM

    Redis 集群中使用 zset:zset 是一种有序集合,将元素与评分关联。分片策略: a. 哈希分片:根据 zset 键的哈希值分布。 b. 范围分片:根据元素评分划分为范围,并将每个范围分配给不同的节点。读写操作: a. 读操作:如果 zset 键属于当前节点的分片,则在本地处理;否则,路由到相应的分片。 b. 写入操作:始终路由到持有 zset 键的分片。

    redis数据怎么清空redis数据怎么清空Apr 10, 2025 pm 10:06 PM

    如何清空 Redis 数据:使用 FLUSHALL 命令清除所有键值。使用 FLUSHDB 命令清除当前选定数据库的键值。使用 SELECT 切换数据库,再使用 FLUSHDB 清除多个数据库。使用 DEL 命令删除特定键。使用 redis-cli 工具清空数据。

    redis过期策略怎么设置redis过期策略怎么设置Apr 10, 2025 pm 10:03 PM

    Redis数据过期策略有两种:定期删除:定期扫描删除过期键,可通过 expired-time-cap-remove-count、expired-time-cap-remove-delay 参数设置。惰性删除:仅在读取或写入键时检查删除过期键,可通过 lazyfree-lazy-eviction、lazyfree-lazy-expire、lazyfree-lazy-user-del 参数设置。

    See all articles

    热AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智能驱动的应用程序,用于创建逼真的裸体照片

    AI Clothes Remover

    AI Clothes Remover

    用于从照片中去除衣服的在线人工智能工具。

    Undress AI Tool

    Undress AI Tool

    免费脱衣服图片

    Clothoff.io

    Clothoff.io

    AI脱衣机

    AI Hentai Generator

    AI Hentai Generator

    免费生成ai无尽的。

    热门文章

    R.E.P.O.能量晶体解释及其做什么(黄色晶体)
    3 周前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳图形设置
    3 周前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.如果您听不到任何人,如何修复音频
    3 周前By尊渡假赌尊渡假赌尊渡假赌
    WWE 2K25:如何解锁Myrise中的所有内容
    3 周前By尊渡假赌尊渡假赌尊渡假赌

    热工具

    适用于 Eclipse 的 SAP NetWeaver 服务器适配器

    适用于 Eclipse 的 SAP NetWeaver 服务器适配器

    将Eclipse与SAP NetWeaver应用服务器集成。

    MinGW - 适用于 Windows 的极简 GNU

    MinGW - 适用于 Windows 的极简 GNU

    这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

    SublimeText3 Mac版

    SublimeText3 Mac版

    神级代码编辑软件(SublimeText3)

    VSCode Windows 64位 下载

    VSCode Windows 64位 下载

    微软推出的免费、功能强大的一款IDE编辑器

    SublimeText3 英文版

    SublimeText3 英文版

    推荐:为Win版本,支持代码提示!