`
flylynne
  • 浏览: 376006 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Redis是单线程的以及Redis为什么这么快

 
阅读更多

Redis简介

Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。

它支持多种类型的数据结构,如字符串(Strings),散列(Hash),列表(List),集合(Set),有序集合(Sorted Set或者是ZSet)与范围查询,Bitmaps,Hyperloglogs 和地理空间(Geospatial)索引半径查询。其中常见的数据结构类型有:String、List、Set、Hash、ZSet这5种。

Redis 内置了复制(Replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(Transactions) 和不同级别的磁盘持久化(Persistence),并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(High Availability)。

Redis也提供了持久化的选项,这些选项可以让用户将自己的数据保存到磁盘上面进行存储。根据实际情况,可以每隔一定时间将数据集导出到磁盘(快照),或者追加到命令日志中(AOF只追加文件),他会在执行写命令时,将被执行的写命令复制到硬盘里面。您也可以关闭持久化功能,将Redis作为一个高效的网络的缓存数据功能使用。

Redis不使用表,他的数据库不会预定义或者强制去要求用户对Redis存储的不同数据进行关联。

数据库的工作模式按存储方式可分为:硬盘数据库和内存数据库。Redis 将数据储存在内存里面,读写数据的时候都不会受到硬盘 I/O 速度的限制,所以速度极快。

 

Redis到底有多快

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO;

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

以上几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:

(1)多路 I/O 复用模型

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。

这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

 

redis的多路复用, 提供了select, epoll, evport, kqueue几种选择,在编译的时候来选择一种。

 

select是POSIX提供的, 一般的操作系统都有支撑;

epoll 是LINUX系统内核提供支持的;

evport是Solaris系统内核提供支持的;

kqueue是Mac 系统提供支持的;

我们一般运行的服务器都是LINUX系统上面, 并且我对Solaris和Mac系统不是很了解, 我们这里重点比较一下select、poll和epoll 3种多路复用的差异。

 

select: 单个进程所能打开的最大连接数有FD_SETSIZE宏定义, 其大小为1024或者2048; FD数目剧增后, 会带来性能问题;消息传递从内核到与到用户空间,需要copy数据;

 

性能问题: 

(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大 

(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

 

poll: 基本上与select一样, 不通点在于没有FD数目的限制, 因为底层实现不是一个数组, 而是链表;

 

epoll: FD连接数虽然有限制, 但是很大几乎可以认为无限制;epoll内核中实现是根据每个fd上的callback函数来实现的,只有活跃的socket才会主动调用callback,所以在活跃socket较少的情况下,使用epoll没有前面两者的线性下降的性能问题; 内核和用户通过共享内存来传递消息;

 

 

那么为什么Redis是单线程的

官方FAQ表示,因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了

 

警告1:这里我们一直在强调的单线程,只是在处理我们的网络请求的时候只有一个线程来处理,一个正式的Redis Server运行的时候肯定是不止一个线程的,这里需要大家明确的注意一下

 

注意点

1、我们知道Redis是用”单线程-多路复用IO模型”来实现高性能的内存数据服务的,这种机制避免了使用锁,但是同时这种机制在进行sunion之类的比较耗时的命令时会使redis的并发下降。因为是单一线程,所以同一时刻只有一个操作在进行,所以,耗时的命令会导致并发的下降,不只是读并发,写并发也会下降。而单一线程也只能用到一个CPU核心,所以可以在同一个多核的服务器中,可以启动多个实例,组成master-master或者master-slave的形式,耗时的读命令可以完全在slave进行。

 

在多核 CPU 服务器上面,Redis 的性能还依赖NUMA 配置和处理器绑定位置。最明显的影响是 redis-benchmark 会随机使用CPU内核。为了获得精准的结果,需要使用固定处理器工具(在 Linux 上可以使用 taskset)。最有效的办法是将客户端和服务端分离到两个不同的 CPU 来高校使用三级缓存。

扩展

几种模型

1、单进程多线程模型:MySQL、Memcached、Oracle(Windows版本);

2、多进程模型:Oracle(Linux版本);

3、Nginx有两类进程,一类称为Master进程(相当于管理进程),另一类称为Worker进程(实际工作进程)。启动方式有两种:

(1)单进程启动:此时系统中仅有一个进程,该进程既充当Master进程的角色,也充当Worker进程的角色。

(2)多进程启动:此时系统有且仅有一个Master进程,至少有一个Worker进程工作。

(3)Master进程主要进行一些全局性的初始化工作和管理Worker的工作;事件处理是在Worker中进行的。

 

redis和memcached的区别

1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;

2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;

3、虚拟内存--Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;

4、过期策略--memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10;

5、分布式--设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从;

6、存储数据安全--memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);

7、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;

8、Redis支持数据的备份,即master-slave模式的数据备份;

 

Redis 只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁 盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据 是不会进行swap操作的。

由于Redis将内存中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个操作,直到子线程完成swap操作后才可以进行修改。

当 从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。 这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。Redis运行我们设置I/O线程 池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。

 

数据一致性(事务支持)
Memcache 在并发场景下,用cas保证一致性
redis事务支持比较弱,只能保证事务中的每个操作连续执行
mongoDB不支持事务
7、数据分析
mongoDB内置了数据分析的功能(mapreduce),其他不支持
8、应用场景
redis:数据量较小的更性能操作和运算上
memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用sharding)
MongoDB:主要解决海量数据的访问效率问题   

分享到:
评论

相关推荐

    「Redis」Redis是单线程的,但Redis为什么这么快?

    「Redis」Redis是单线程的,但Redis为什么这么快?

    为什么说Redis是单线程的以及Redis为什么这么快!

    简单解释下第二条:上下文切换就是cpu在多线程之间进行轮流执行(枪战cpu资源),而redis单线程的,因此避免了繁琐的多线程上下文切换。 重点解释下多路复用: 多路-指的是多个socket连接,复用-指的是复用一个线程...

    20_来聊聊redis的线程模型吧?为啥单线程还能有很高的效率?.zip

    Redis是一款高性能的键值存储系统,它以其独特的单线程模型和高效的内存管理而闻名。在深入了解Redis的线程模型之前,我们先要明白一点:虽然Redis是单线程的,但它的性能并不低,反而在很多场景下表现出非常高的...

    Redis经典面试题:redis是单线程架构还是多线程架构

    Redis,作为一种高性能的键值存储系统,以其独特的单线程模型和高效的内存操作而闻名。在Redis中,大部分操作都是基于内存的,这使得它在处理读取和写入操作时速度极快。Redis的数据结构设计也非常巧妙,包括简单...

    redis面试题之单线程.zip

    虽然Redis单线程模型无法同时处理多个客户端的请求,但它可以通过快速响应和pipeline批量处理来提高并发性。客户端可以将多个命令一次性发送到服务器,减少网络往返次数。 3.2 CPU瓶颈 随着请求量的增加,单线程...

    异步 redis client.rar

    Redis单线程为什么还能这么快? 因为Redis是基于内存的,所有的运算都是内存级别的,而且单线程避免了多线程的切换性能耗损问题。 Redis单线程如何处理那么多并发客户端连接? 这里就要扯到NIO多路复用模型了,由于...

    cpp-在redis30上实现多线程implementmultithreadinginredis30

    Redis 是一个高性能的键值存储系统,以其单线程模型而闻名。然而,在 Redis 3.0 版本中,引入了多线程的概念来优化 I/O 处理,特别是针对网络读写操作,以此来进一步提升性能。下面将详细讨论如何在 Redis 3.0 中...

    redis单线程快的原因和原理

    下面我们将详细探讨Redis单线程快速响应的原因和原理。 首先,Redis之所以快速,首要原因是它执行所有操作都在内存中,不涉及磁盘I/O。内存操作避免了磁盘访问的延迟,使得数据读写速度显著提升。Redis将数据存储在...

    redis-windows-redis7.0.5.zip

    2. **单线程模型**:Redis采用单线程处理客户端请求,避免了多线程间的上下文切换开销,提升了处理性能。 3. **数据结构优化**:Redis内置丰富的数据结构,如String、Hash、List、Set、Sorted Set,这些数据结构的...

    redis单机安装完整例子

    它的高性能源于其内存存储和单线程模型。 二、安装Redis 1. 下载:首先从官方GitHub仓库或者官方网站下载最新版的Redis源码包,例如`redis-stable.tar.gz`。 2. 解压:将下载的压缩包解压到任意目录,例如`/usr/...

    lixd#daily-notes#为什么Redis选择单线程1

    2. 引入多线程 3. 总结 4. 原文

    头歌初识redis答案.rar

    Redis使用单线程处理请求,这是因为对于内存系统来说,没有上下文切换的效率是最高的。 二、Redis Key的基本命令 EXISTS name:判断当前key是否存在,其中name可以替换为其他key。 MOVE name db:将key从当前数据库...

    redis为什么快.docx

    综上所述,Redis 的高性能主要得益于其内存存储、非阻塞IO、单线程模型、优化的数据结构以及高效的事件处理器。这些设计使得Redis在处理大量并发请求时能够表现出卓越的性能,成为现代Web应用中广泛使用的数据存储和...

    redis-windows-7.2.1.zip

    此外,由于Redis是单线程模型,所以如果需要处理高并发,可以考虑启动多个实例或者使用哨兵(Sentinel)系统来管理多个Redis实例。 总之,Redis是一个强大且灵活的数据库,适用于多种用途。在Windows上安装和使用...

    Redis集群数据迁移操作文档

    实际迁移过程中,我们以两个场景为例:一是从一个Redis集群(Cluster_A)迁移到另一个Redis集群(Cluster_B),二是从Redis集群(Cluster_A)迁移到单个Redis实例(Redis_C)。在迁移前,务必先检查源和目标Redis...

    Redis安装包 Redis-x64-3.2.100.zip

    - 单线程模型:Redis采用单线程模型处理客户端请求,避免了多线程的上下文切换开销,提高了性能。 - 内存管理:Redis使用内存优化技术,如对象共享和压缩表,来减少内存使用并提高效率。 - 集群支持:虽然3.2版本...

    Redis中的String类型及使用Redis解决订单秒杀超卖问题

    Redis是单线程的,比如SetAll & AppendToValue & GetValues & GetAndSetValue & IncrementValue & IncrementValueBy等等,这些看上去像是组合命令,但实际上是一个具体的命令,是一个原子性的命令,不可能出现中间...

Global site tag (gtag.js) - Google Analytics