高性能的服务器,不一定是多线程实现的,也就是说多线程不一定比单线程效率高,这得分具体的情况。以redis为例,核心处理请求的线程只有一个,所以我们常常理解其仅仅只有一个线程,但准确来说其实并不是单线程的,比如日志的备份需要单独的fork一个进程或者线程去做备份等,那么redis何来单线程还能达到如此10万+的qps呢?其实这取决于具体的实现,redis采用了基于高性能Reactor的IO多路复用的模式+内存数据结构+单线程处理网络请求这几块,决定了其性能高的原因。
我们知道操作系统的主要资源有CPU,内存,磁盘,带宽,而对存储介质访问速度肯定是CPU缓存>内存>磁盘。
redis 核心就是 如果我的数据全都在内存里,我单线程的去操作 就是效率最高的,为什么呢,因为多线程的本质就是 CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。redis 用 单个进程或者线程 绑定一块CPU,从而最大化提升该进程访问特定CPU缓存的速度,然后针对这块Cache内存的数据进行多次读写的时候,都是在一个CPU上完成的,所以它是单线程处理这个事。在内存的情况下,这个方案就是最佳方案 —— 阿里 沈询
那么什么时候事务需要用到多线程呢?这个问题的本质取决于下层所使用的存储,如果是内存操作,则可以动态地申请和销毁内存块;而磁盘的IOPS很低,但吞吐量很高。如果一个场景涉及多次读写操作,单线程可以很高的效率对于内存进行读写操作;但是,由于磁盘的IOPS仅为内存的几千分之一,如果依旧用操作内存的方式操作磁盘,那系统的整体性能将会很低,这意味着必须将大量的读写操作聚合成一个Batch后再提交时才能达到较好的性能。而将大量请求攒到一起的方式一是异步,也就是请求本身和线程不绑定,线程可以不Block(本质来说还是一种多线程的方式),处理完一个线程后再处理其他线程。这种做法的核心是将大量不同的请求提交到一个Buffer中,再由该Buffer统一读取或者写入磁盘,从而提高效率。在慢速设备中,多线程或异步非常常见,在设计系统时,面对磁盘、网络、SSD等慢速设备必须考虑使用多线程。
方法就是用异步:将请求和处理的线程不绑定,请求的线程将请求放在一个buff里,然后等buff快满了,处理的线程再去处理这个buff。然后由这个buff 统一的去写入磁盘,或者读磁盘,这样效率就是最高。 java里的NIO, 大名鼎鼎的netty 就是这么干的,对于慢速存储设备磁盘,网络,SSD,这种处理方式异步+多线程+写缓冲区buffer就是最佳的。
其实原理的东西就这么些,本身都是操作系统相关的东西,并不复杂
为何单线程绑定一个cpu效率最高,CPU 是一个重要的影响因素,由于是单线程模型,Redis 更喜欢大缓存快速 CPU(主频高), 而不是多核,在多核 CPU 服务器上面,Redis 的性能还依赖 NUMA 配置和 处理器绑定位置。 最明显的影响是 redis-benchmark 会随机使用 CPU 内核。为了获得精准的结果,需要使用固定处理器工具(在 Linux 上可以使用 taskset)。 最有效的办法是将客户端和服务端分离到两个不同的 CPU 来高校使用三级缓存。
(1)redis作为单进程模型的程序,为了充分利用多核CPU,常常在一台server上会启动多个实例。而为了减少切换的开销,有必要为每个实例指定其所运行的CPU。
(2) Linux 上 taskset 可以将某个进程绑定到一个特定的CPU。你比操作系统更了解自己的程序,为了避免调度器愚蠢的调度你的程序,或是为了在多线程程序中避免缓存失效造成的开销。
总结一下,redis单线程性能出色的必要条件:
(1)以内存为主要存储结构,这是快的前提
(2)高性能的基于epoll的IO多路复用模式
(3)单进程/单线程直接绑定CPU,避免OS无用调度和上下文切换
分享到:
相关推荐
尽管Redis的单线程模型在大多数场景下表现出色,但在Redis 6.0版本中,引入了多线程的概念,主要是为了优化网络IO读写性能。这里的多线程仅用于数据的读写操作,命令执行仍保持单线程顺序执行,因此不会引发线程安全...
根据测试结果,redis在单线程set和get操作中表现出色,但在高并发set操作且数据大小为100KB时面临挑战。memcache在并发get操作中表现良好,但在其他场景下略逊一筹。tair在各种场景下的性能都较为稳定,但在高并发和...
Redis以其内存存储、单线程模型和丰富的数据结构(如字符串、哈希、列表、集合、有序集合)而闻名,这使得它在读写速度上表现出色。它的性能主要体现在以下几个方面: - 高速读写:由于数据存储在内存中,Redis的...
综上所述,Redis 的高性能主要得益于其内存存储、非阻塞IO、单线程模型、优化的数据结构以及高效的事件处理器。这些设计使得Redis在处理大量并发请求时能够表现出卓越的性能,成为现代Web应用中广泛使用的数据存储和...
虽然这听起来可能会限制性能,但由于Redis操作基本上都是内存中的数据操作,这使得它的性能在实际使用中并不受单线程的限制。相反,单线程模型还避免了多线程编程中的复杂性和并发问题。 订阅/发布模型是Redis提供...
早期版本的Redis采用的是单线程模型,这使得它在处理I/O操作时效率很高,因为避免了线程切换的开销。然而,随着Redis的发展,为了适应大规模并发场景,新版Redis引入了多线程模型。虽然核心的命令处理仍保持单线程,...
在标签中提到了“windows”,这意味着Redis不仅在Linux环境下表现出色,也可以很好地在Windows操作系统上运行,为跨平台开发提供了便利。对于那些习惯Windows环境的开发者来说,这是一个重要的优势。 总结起来,...
首先,此版本可能包含了多线程支持,这是一个重大改进,因为Redis以前是单线程模型,这限制了其在多核处理器上的扩展性。多线程能够提高处理客户端请求的速度,特别是在执行CPU密集型操作时。 “redis.windows.conf...
2. 单线程模型:尽管Redis是单线程处理命令,但由于其优化的I/O多路复用模型,仍能高效处理并发请求。 3. 主从复制:通过主从复制,可以提高读取性能并实现数据冗余,提高系统的可用性。 三、Redis持久化 1. RDB...
Redis 3.2.7 是 Redis 的一个重要版本,它提供了稳定性和性能的改进,同时也引入了一些新特性。 首先,让我们详细了解一下Redis的核心概念: 1. **数据类型**:Redis支持五种基本数据类型,包括字符串(Strings)、...
这些知识点总结了 Redis 的特点、性能优势、多种数据结构支持、设置 expire 时间、主要缺点、数据类型、为什么需要将所有数据放到内存中、单进程单线程、虚拟内存、分布式 Redis、读写分离模型、数据分片模型和回收...
NoSQL 数据库的主要特点包括易扩展性、大数据量下的高性能、多样化数据类型以及弱一致性等,这些特性使得 Redis 在应对大规模高并发场景时表现出色。 Redis 的核心特点是其基于内存的存储机制,这使得 Redis 具有极...
3. **并发访问与性能**:Redis通过单线程模型处理客户端请求,避免了多线程竞争资源导致的锁开销,从而提高了处理速度。然而,对于百万级别的并发访问,单线程模型可能会成为瓶颈。此时,可以通过增加Redis实例、...
Redis使用了单线程模型,通过epoll的事件驱动机制来处理客户端连接。这种方式虽然限制了Redis在同一时间只能处理一个客户端请求,但避免了多线程同步带来的复杂性,且在处理大量短连接时表现出色。 最后,Redis的...
11. 性能优化:Redis是单线程模型,通过非阻塞I/O多路复用技术如epoll或kqueue,可以高效处理大量并发连接。此外,合理的配置参数调整也是提升性能的关键。 12. Redis 2.8.19 版本:这个版本可能包含了一些bug修复...
首先,此版本引入了多线程I/O模型,虽然Redis主要依赖单线程执行命令,但在这个版本中,网络I/O部分已经实现异步处理,提高了网络通信效率,降低了CPU资源的占用。其次,3.0.1版修复了多个已知的bug,增强了系统的...
- Redis为了简化并发控制和提高性能,选择单线程模型。它利用内部操作的原子性避免了线程安全问题,但限制了多核CPU的利用率。 - 对于多核CPU的利用,可以通过在同一台机器上启动多个Redis实例来实现水平扩展。 4...
关于Redis是否是单线程的问题,实际上Redis并不是真正的单线程,而是单进程模型,并且在执行过程中大多数操作都是单线程的。但Redis的某些操作,如持久化、异步删除、集群数据同步等,是由后台线程执行的。之所以...
总结来说,Redis的核心数据结构提供了多样化的数据操作,而其高性能原理则在于内存存储、单线程模型、持久化策略以及各种优化技术的综合运用。了解和掌握这些知识点,对于有效利用Redis解决实际问题具有重要意义。