🚀 Database
1、数据库基础
1.1 事务的概念和特性
1.2 锁
1.3 锁协议
1.4 事务日志
1.5 MVCC实现原理
1.6 基础知识
1.6.1 三范式
1.6.2 多表连接方式
1.6.3 存储过程
1.6.4 TRUNCATE和DROP的区别
1.6.5 触发器
1.6.6 视图
2、MySQL
2.1 索引
2.2 索引组织表
2.3 InnoDB和MyISAM的区别
2.4 Checkpoint技术
2.5 宕机恢复原理
2.6 数据库优化
2.7 分库分表
2.8 一致性哈希算法
2.9 主从复制
3、Redis
3.1 概述
3.1.1 为什么Redis单线程还这么快
3.1.2 Redis数据类型
3.1.3 持久化机制
3.1.4 过期机制和内存淘汰策略
3.2 线程模型
3.3 分布式问题
3.3.1 Redis实现分布式锁
3.4 缓存异常
3.4.1 缓存击穿、缓存雪崩
3.5 高可用
3.5.1 主从复制
3.5.2 哨兵模式
3.5.3 集群模式
-
+
游客
注册
登录
为什么Redis单线程还这么快
> 严格来说,**Redis Server是多线程的**,**只是他的请求处理整个流程是单线程处理的**,**我们平时所说的Redis单线程快是指他的请求处理过程非常地快**。 Redis的性能非常之高,每秒可以承受10W+的QPS,他如此优秀的性能主要取决于一下几个方面: 1. **纯内存操作**。 2. **使用I/O多路复用技术**。 3. **非CPU密集型任务**。 4. **单线程的优势**。 5. **多线程优化**。 ## 1 纯内存操作 1. Redis**是一个内存数据库**,他的**数据都存储在内存中**,这意味着我们**读写数据都是在内存中完成**,**这个速度是非常快的**。 2. Redis**是一个KV内存数据库**,他**内部构建了一个哈希表**,**根据指定的Key访问时**,**只需要$O(1)$的时间复杂度就可以找到对应的数据**,同时,Redis**提供了丰富的**[数据类型](https://notebook.ricear.com/project-37/doc-805),并**使用高效的操作方式进行操作**,**这些操作都在内存中进行**,并**不会大量消耗CPU资源**,所以**速度极快**。 ## 2 使用IO多路复用技术 > 为什么Redis中要使用I/O多路复用这种技术呢? > > 这是因为**Redis是跑在单线程中的**,**所有的操作都是按照顺序线性执行的**,**但是由于读写操作等待用户输入或输出都是阻塞的**,**所以I/O操作在一般情况下往往不能直接返回**,**这会导致某一文件的I/O阻塞导致整个进程无法对其他客户提供服务**,而**I/O多路复用就是为了解决这个问题而出现的**。 1. Redis**采用了[IO多路复用技术](https://notebook.ricear.com/project-26/doc-335/#3-3-IO-%E5%A4%9A%E8%B7%AF%E5%A4%8D%E7%94%A8)和[非阻塞IO](https://notebook.ricear.com/project-26/doc-335/#3-2-%E9%9D%9E%E9%98%BB%E5%A1%9E-IO)**,这个技术**由操作系统实现提供**,Redis**可以方便地操作系统的API**。 2. Redis**可以在单线程中监听多个Socket的请求**,**在任意一个Socket可读/可写时**,Redis**去读取客户端请求**,**在内存中操作对应的数据**,**然后再写会到Socket中**,**整个过程非常高效**,Redis**利用了IO多路复用技术的[事件驱动模型](https://notebook.ricear.com/project-37/doc-807)**,**保证在监听多个Socket连接的情况下**,**只针对有活动的Socket采取反应**。 ## 3 非CPU密集型任务 1. 采用**单线程的缺点**很明显,**无法使用多核CPU**,但是**由于Redis的大部分操作并不是CPU密集型任务**,**Redis的瓶颈在于内存和网络带宽**,因此**在高并发请求下**,**Redis需要更多的内存和更高的网络带宽**,否则**瓶颈很容易出现在内存不够用和网络延迟等待的情况**。 2. **如果我们觉得单个Redis实例的性能不足以支撑业务**,**Redis作者推荐部署多个Redis节点**,**组成集群的方式来利用多核CPU的能力**,**而不是在单个实例上使用哪个多线程来处理**。 ## 4 单线程优势 1. 基于以上特性,Redis**采用单线程已足够达到非常高的性能**,所以Redis**没有采用多线程模型**。 2. 单线程模型带来了以下好处: 1. **没有了多线程上下文切换的性能损耗**。 2. **没有了访问共享资源加锁的性能损耗**。 3. **开发和调试非常友好**,**可维护性高**。 3. 单线程模型同时也具有缺点,最大的缺点是**如果前一个请求发生耗时比较久的操作**,**那么整个Redis就会阻塞住**,**其他请求也无法进来**,**直到这个耗时久的操作处理完成并返回**,**其他请求才能被处理到**,我们平时遇到Redis变慢或长时间阻塞的问题,90%也都是因为Redis处理请求是单线程这个原因导致的,所以**我们平时在使用Redis时**,**一定要避免非常耗时的操作**,例如**使用时间复杂度过高的方式获取数据**、**一次性获取过多的数据**、**大量key集中[过期]()导致Redis[淘汰](https://notebook.ricear.com/project-37/doc-812)key压力变大等等**,**这些场景都会阻塞住整个处理线程**,**知道他们处理完成**,**势必会影响业务的访问**。 ## 5 多线程优化 1. **Redis Server本身是多线程的**,**除了请求处理流程是单线程处理之外**,**Redis还有其他工作线程在后台执行**,**他负责异步执行某些比较耗时的任务**,例如[AOF](https://notebook.ricear.com/project-37/doc-806/#2-2-AOF)每秒刷盘、[AOF文件重写](https://notebook.ricear.com/project-37/doc-806/#2-2-3-AOF-%E9%87%8D%E5%86%99)都是在另一个线程中完成的。 2. **在Redis 4.0之后**,Redis**引入了 `lazyfree`机制**,**提供了 `unlink`**、`flushall async`、`flushdb async`**等命令和 `lazyfree-lazy-eviction`**、`lazyfree-lazy-expire`**等机制来异步释放内存**,他**主要是为了解决在释放大内存数据导致整个Redis阻塞的性能问题**,因为**在删除大 `key`时**,**释放内存往往都比较耗时**,所以Redis**提供异步释放内存的方式**,**让这些耗时的操作放到另一个线程中异步去处理**,**从而不影响主线程的执行**,**提高性能**。 3. **到了Redis 6.0**,Redis又**引入了多线程来完成请求数据的协议解析**,**进一步提升性能**,他**主要是解决高并发场景下**,**单线程解析请求数据协议带来的压力**,**请求数据的协议解析由多线程完成之后**,**后面的请求处理阶段依旧还是单线程排队处理**。 ## 参考文献 1. [几率大的 Redis 面试题(含答案)](https://blog.csdn.net/Butterfly_resting/article/details/89668661)。 2. [Redis 面试题(总结最全面的面试题)](https://juejin.cn/post/6844904127055527950)。 3. [面试官:Redis 为什么这么快?除了基于内存操作还有其他原因吗?](https://zhuanlan.zhihu.com/p/160157573) 4. [Redis 是单线程的,但 Redis 为什么这么快?](https://juejin.cn/post/6844903663224225806) 5. [Redis 为什么是单线程?为什么有如此高的性能?](https://juejin.cn/post/6844903814500220936) 6. [为什么Redis单线程还这么快?](http://kaito-kidd.com/2020/06/28/why-redis-so-fast)
ricear
2021年10月16日 17:48
©
BY-NC-ND(4.0)
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码