REDIS是单线程处理所有请求,和一般经典实际上推荐的方式相反,那么单线程串行处理,为什么依然能够做到很快呢?知乎上的一个答案如下,其中线程切换和锁不是性能主要影响因素的观点和一般的答案都不同
作者:杨海坡
链接:https://www.zhihu.com/question/19764056/answer/20241839
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

纯内存数据库,如果只是简单的 key-value,内存不是瓶颈。一般情况下,hash 查找可以达到每秒数百万次的数量级。

瓶颈在于网络 IO 上。

根据你测的的 10000/s 来看,客户端和 redis 应该是部署在两台不同的机器,并且是使用同步的方式请求 redis. 每次请求需要通过网络把请求发送到 redis 所在的机器,然后等待 redis 返回数据。时间大部分消耗在网络传输中。

如果把 redis 和客户端放在同一台机器,网络延迟会更小,一般情况下可以打到 60000 次每秒甚至更高,取决于机器性能。

锁不是影响性能的主要因素。线程锁 (mutex_lock) 只有在遇到冲突的情况下性能会下降,而正常情况下,遇到冲突的概率很低。如果只是简单的加锁、释放锁速度是非常快的,每秒钟上千万次没问题。memcache 内部用到了大量的锁,并没有见到性能降低。

线程也不是影响吞吐量的重要因素。如第一点来说,一般情况下,程序处理内存数据的速度远高于网卡接收的速度。使用线程好处是可以同时处理多条连接,在极端情况下,可能会提高响应速度。

使用 epoll 或 libevent 等因为异步非阻塞 IO 编程只能这么做。与之对应的是同步阻塞 IO 编程,使用多进程或多线程实现多条连接的处理,比如 apache。一般情况下,异步非阻塞 IO 模型性能是远高于同步阻塞 IO 模型的,可以参考 nginx 与 apache 性能的对比。

libevent 并不比 redis 自己实现的 ae_event 慢,代码多是应为 ae_event 只实现了 redis 需要的功能,而 libevent 则具有更多的功能,比如更快的定时器、buffer event 模型,甚至自带了 DNS、HTTP 协议的处理。并且 libevent 更通用,而 redis 只专注于 linux 平台。

最后回答题主问题,快在哪?
1、纯内存操作
2、异步非阻塞 IO

 
本博客的个人观点:
1. REDIS很注重让线程的每次操作都尽量简短,会将功能细分成多个逻辑块,每个逻辑块都分别让线程在自己的独立的时间片完成,而不是一个时间片做整个功能。
    比如,主从服务器的复制功能。从服务器收到SLAVE OF的命令后,会记录信息,然后交由serverCron来进行socket建链,然后再次交由serverCron进行slave向master的ping操作,然后再次交由serverCron进行Pong的接收。这样其他功能在每次功能块执行结束后都能被执行,而不至于线程的时间都堵塞在某一个功能上。
 
REDIS epoll 讲解
https://www.cnblogs.com/yuxingfirst/archive/2012/11/18/2776012.html
 
/* Include the best multiplexing layer supported by this system.
 * The following should be ordered by performances, descending. */
#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
    #ifdef HAVE_EPOLL
    #include "ae_epoll.c"
    #else
        #ifdef HAVE_KQUEUE
        #include "ae_kqueue.c"
        #else
        #include "ae_select.c"
        #endif
    #endif
#endif

建链流程:
2 initServer->aeCreateEventLoop->aeApiCreate  创建epoll实例  state->epfd = epoll_create(1024);
3.initServer->listenToPort->anetUnixServer->anetTcpServer 创建本地socket fd-1
4. initServer->aeCreateFileEvent->aeApiAddEvent->epoll_ctl(epfd,fd-1);把处理函数acceptTcpHandler注册到wfileProc/rfileProc

5. main->acMain->aeProcessEvents->aeApiPoll->epoll_wait->如果有数据->wfileProc/rfileProc 回调到 acceptTcpHandler->accept,建链完成
建链完成后,会针对这个新的fd创建redis client结构

而在client的创建过程中,createClient会再次注册一个event,回调函数readQueryFromClient,来进行从这个新socket的数据的接收

单线程的REDIS为什么这么快?的更多相关文章

  1. 性能测试 | 理解单线程的Redis为何那么快?

    前言 Redis是一种基于键值对(Key-Value)的NoSQL数据库,Redis的Value可以由String,hash,list,set,zset,Bitmaps,HyperLogLog等多种数 ...

  2. Redis 为什么这么快?

    1. 纯内存操作,肯定快 数据存储在内存中,读取的时候不需要进行磁盘的 IO 2. 单线程,无锁竞争损耗 单线程保证了系统没有线程的上下文切换 使用单线程,可以避免不必要的上下文切换和竞争条件,没有多 ...

  3. Redis为什么这么快?

    Redis为什么这么快?

  4. 硬核!15张图解Redis为什么这么快

    作为一名服务端工程师,工作中你肯定和 Redis 打过交道.Redis 为什么快,这点想必你也知道,至少为了面试也做过准备.很多人知道 Redis 快仅仅因为它是基于内存实现的,对于其它原因倒是模棱两 ...

  5. 为什么单线程的Redis这么快?

    一. Redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(li ...

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

    参考文章:https://blog.csdn.net/xlgen157387/article/details/79470556 redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用 ...

  7. 为什么说Redis是单线程的以及Redis为什么这么快!(转)

    文章转自https://blog.csdn.net/chenyao1994/article/details/79491337 一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到 ...

  8. Redis为什么是单线程、及高并发快的3大原因详解

    Redis的高并发和快速原因 1.redis是基于内存的,内存的读写速度非常快: 2.redis是单线程的,省去了很多上下文切换线程的时间: 3.redis使用多路复用技术,可以处理并发的连接.非阻塞 ...

  9. 《为什么说Redis是单线程的以及Redis为什么这么快!》

    为什么说Redis是单线程的以及Redis为什么这么快!   一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是“二八定律”.什么是“热数据和冷数据”,复杂一点的会问到缓 ...

随机推荐

  1. 基于js的APP多语言处理

    本文出自APICloud官方论坛, 感谢论坛版主哼哼哈兮 的分享.   本期分享一个js的多语言处理插件i18n.js,此插件是基于JQuery.i18n.properties修改而来的. 实现的原理 ...

  2. Spring-cloud微服务实战【一】:微服务的概念与演进过程

    本文是一个系列文章,主要讲述使用spring-cloud进行微服务开发的实战.在开始之前,我们先说一下从传统的单一部署架构到微服务的发展过程,以便让童鞋们更好的理解微服务的概念与演进过程. 1.单体架 ...

  3. 《C# 爬虫 破境之道》:第一境 爬虫原理 — 第二节:WebRequest

    本节主要来介绍一下,在C#中制造爬虫,最为常见.常用.实用的基础类 ------ WebRequest.WebResponse. 先来看一个示例 [1.2.1]: using System; usin ...

  4. 19南京网络赛B 欧拉降幂

    题目链接 给a,b,p.有b个a的幂 #include <iostream> using namespace std; typedef long long LL; const LL N = ...

  5. 自定义博客cnblogs样式的必备前端小知识——js、jq

    JQ.JS相关小知识 任意元素自动点击 $(".editicon").trigger('click') 添加子元素 append() - 在被选元素的结尾插入内容 prepend( ...

  6. python 文件监听

    对文件进行监听.过滤 def tail(filename): f = open(file=filename, mode='r', encoding='utf-8') # 打开文件不能用with,因为监 ...

  7. python 进程Queue

    1.作用:进程之间的数据交互 2.常用方法 """ 对象.put() 作用:放入队列一个数据 对象.get() 作用:取队列一个数据,若队列没有值,则阻塞 对象.empt ...

  8. 11、python模块的导入

    前言:本文主要介绍python模块的导入,包括模块的定义.模块的作用.导入方式以及模块的搜索路径. 一.模块的定义 python模块(module),简单来说就是一个python文件,以.py结尾,文 ...

  9. 18年第一弹射 和网络有关; 艾曲塞嗯诶系列篇 one

    1:当指定接口运行在RIP2组播方式时,以下说法正确的是 2个答案 A 只接收RIPv2组播报文 B  不接收RIPV1 广播报文 2 下面哪条命令是把PPP的认证方式设置为PAP? C ppp au ...

  10. typescript step by step interface class