xiaohanliang
Database
Database
  • review
  • MySQL
    • 0. 索引就是树吗
    • 1. 索引是怎么发挥作用的
    • 2. 聊聊怎么估时间
    • 3. 主键玄学
    • 4. 事务的执行过程@ACD
    • 5. MVCC就是用undolog回退
    • 6. 事务如何彼此隔离@I
    • 7. 如何人为的制造死锁
    • 8. 引擎是干什么的
    • 9. 主从复制怎么做到的
    • 10. 寻找同步起始点GTID
    • 11. 预解析Statement
  • Redis
    • 0. Hash@数据结构
    • 1. ZSet@数据结构
    • 2. 场景与玩法@数据结构
    • 3. 可能的风险点
    • 4. Redis的落盘
    • 5. 关于效率的讨论
    • 6. 主从模式@集群化
    • 7. [WIP]Proxy实现@集群化
    • 8. 标准玩法@集群化
  • KV/Distributed
    • 0. 面临的问题
    • 1.Raft@原理
    • 2. LSM@原理
    • 3. [WIP]分布式事务@原理
Powered by GitBook
On this page
  • Redis是单线程的
  • 如何处理网络IO
  • 讨论一下多线程

Was this helpful?

  1. Redis

5. 关于效率的讨论

Previous4. Redis的落盘Next6. 主从模式@集群化

Last updated 4 years ago

Was this helpful?

[toc]

Redis是单线程的

Redis一个比较出名的点, 就是吞吐量如此恐怖的怪兽, 居然是跑在单线程上的, 即使到今天, 他的绝大部分常用功能依旧是单线程的. 这一节我们会介绍为什么Redis会这么钟爱单线程.

首先单线程不代表客户端的请求是串行/顺序执行的, 单线程也能并发处理客户端请求, 我们上一节介绍了IO Multiplexing, 这使得我们一次性可以接非常多的请求, 然后那个fd先就绪那个先响应.

继续, 设想一下, 如果你每秒都能处理百万级的请求, 但是你还是使用单线程, 那么是不是说明单线程对你来说就已经够用了? 那么我们把这句话延伸一下: 如果单线程就够用, 那就是说Redis对CPU就是无所谓的. 为什么呢? 你需要设想一下Redis的工作模式:

  • Redis并不是一个IO密集型服务:(如果在不开AOF的情况下)基本都不会涉及磁盘IO操作, 它的工作模式就是: 从内存里读, 往内存里写

  • Redis同时也不是一个CPU密集的服务: 因为它也不怎么需要大量计算

  • 这种特征导致, 等待网络IO成为最大的瓶颈

如何处理网络IO

那么Redis你的弱点到底是什么呢? Redis真正的瓶颈在于等待网络IO上, 等待网络传输带来的延迟, 以及等待用户输入中消耗的时间. 这才是真正的问题. "等待网络IO"这种问题我们已经在上一节讨论过了, 合理的处理IO Multiplexing能妥善处理网络IO的问题. 所以Redis对于Multiplexing的处理一定会是一大亮点

Redis内部使用file event handler, 这个文件事件处理器(其实所谓的事件就是指IO就绪), 本身是单线程的, 因此决定了Redis也得是单线程的, 就是这个文件事件处理器搞的IO多路复用, 监听着众多连接其上的socket, 它的结构为:

  • 管理多个连接其上的socket

  • IO多路复用的处理核心

  • 事件分派器

  • 事件处理器: 连接应答, 命令接收, 命令回复

讨论一下多线程

[使用多线程的问题] 不错, 你会说搞多线程, 大家一起读, 这样不会出现有的fd明明已经就绪了, 但是来不及读的情况. 但是多线程的引入会带来一些麻烦: 上锁 / 开发/维护麻烦 / 如果一个Redis里搞了多个线程, 那么线程切换所带来的耗时反而可能导致性能下降.

[不使用多线程的问题] 如果不使用多线程, 那对于多核心的机器就利用的不充分, 对于这个问题的解决, 一个是现在都不会给你一整个机器, 经过虚拟化以后我们主要讨论分到了几个核心, 几个内存, 另外如果真的有好几个核心, 你可以拿来起好几个Redis实例, 用来做主从, 分片, 扩展你缓存的吞吐能力

[为数不多用到了多线程的场景] 我们简单介绍一下. Redis在最新的几个版本里也搞了一些多线程, 举个例子, DEL命令用于删除一个键, 小键好说, 大键的话需要删很久, 这个问题并不是网络IO造成的, 因此Multiplexing在这个问题上也帮不了你. 单线程模型下, 所有人就必须得等你删完才行. 因此对于大键我们是这样办的, 我们先解除这个键与值的匹配, 然后你去搞你的, 我在后台再开一个线程把东西删了