Redis的线程模型和事务
文章插图
1. 前言我原本只是想学习Redis的事务 , 但后来发现 , Redis和传统关系型数据库的事务在ACID的表现上差异很大 。 而要想详细了解其中的缘由 , 就离不开Redis独特的单线程模型 , 因此本文将二者联系在一起讲解 。
下面先会补充一些知识储备 , 包括解答几个常犯错的问题 , 分析Redis的线程模型 , 为后面的章节打好基础 。 随后再讲解Redis的事务实现 , 和关系型数据库的事务做对比 , 以及会附上springboot中实现事务的代码 。
2. 常见问题2.1. 高并发不等于高并行我们最多听到的就是 并发, 但实际上很多时候并不严谨 , 有些情况应该被定义为 并行 :
- 并发, 是指在一个时间段内有多个进程在执行 。 只不过在人的角度看 , 因为这个计算机角度的时间实在是太短暂了 , 人根本就感受不到是多个进程 , 看起来像是同时进行 , 这种是并发 。
- 并行, 指的是在同一时刻有多个进程在同时执行 。
2.2. 什么时候该用多线程我们首先要明确 ,多线程不一定比单线程快 , 因为多线程还涉及到CPU上下文切换的消耗 , 和频繁创建、销毁线程的消耗。 那么多线程是为了优化什么而使用的呢?我所了解的有两点:
1.充分利用多核CPU的资源 , 实现并行
因为多核cpu每一个核心都可以独立执行一个线程,所以多核cpu可以真正实现多线程的并行 。
但这点优化算不上什么 , 一台服务器上一般部署了很多的应用 , 哪有那么多空闲的CPU核心空闲着 。
2.应对CPU的“阻塞”
我认为这才是主要原因 。 “阻塞”包括网络io、磁盘io等这类io的阻塞 , 还包括一些执行很慢的逻辑操作等 。 例如:某个接口的方法中 , 按照执行顺序分成A、B、C三个独立的部分 。
如果每个部分执行的都很慢(如:查询数据库视图 , 将数据导出excel文件) , 都要10秒 。 那么方法执行完成 , 单线程要用30秒 , 多线程分别执行只需要10秒 。 优化了20秒 , 线程创建和CPU上下文切换的影响 , 和20秒比起来不算什么 。
如果每个部分执行的都很快 , 都只需要10毫秒 。 按照上面的计算方式 , 理论上优化了20毫秒 , 可线程创建和CPU上下文切换的影响 , 可是要大于20毫秒的 。
因此总体来说 , 多线程开发对于程序的优化 , 主要体现在应对导致CPU“阻塞”的点 。
3. 线程模型Redis服务端通过单进程单线程 , 处理所有客户端的请求 。
Redis官方数据是说支持100000+ 的QPS(峰值时间的每秒请求) , 很难相信这是靠单线程来支撑的 。 因此我们要探究一下 , Redis的线程模型为啥能支持它执行这么快?
3.1. 性能瓶颈官方表示 , Redis是基于内存操作 , CPU不是Redis的性能瓶颈 , Redis的性能瓶颈是机器的内存和网络带宽 。
看到这句话 , 我有个疑惑 , 为啥 “Redis是基于内存操作 , CPU不是Redis的性能瓶颈” ?
这就联系到第二章中“2.多线程不一定快”的知识点了-- 在多线程开发对于程序的优化 , 主要体现在应对导致CPU“阻塞”的点 。 普通数据库的瓶颈在于磁盘io , 可Redis是基于内存操作 , 没有磁盘io的瓶颈 , 而且基于Reactor模型 , 也没有网络io的阻塞 。 没有多线程的必要 , CPU也就不是Redis的性能瓶颈 。
另外Redis是将所有的数据全部放在内存中的 , 所有说使用单线程去操作执行效率就是最高的 , 多线程在执行过程中需要进行 CPU 的上下文切换 , 这个是耗时操作 。 对于内存系统来说 , 如果没有上下文切换效率就是最高的 , 多次读写都是在一个 CPU 上的 , 在内存情况下 , 这个就是最佳方案 。
推荐阅读
- Google AI建立了一个能够分析烘焙食谱的机器学习模型
- OpenAI推DALL-E模型:能根据文字描述生成图片
- Intel 12代CPU曝光:不只16核24线程
- AMD Zen3线程撕裂者曝料:16核心回归、名字凌乱
- 英特尔Alder Lake-S早期工程样品曝光:16核/24线程 主频仅1.4GHz
- AMD确认Zen3架构新一代锐龙线程撕裂者处理器:要明年见了
- 谷歌搜索的灵魂!BERT模型的崛起与荣耀
- java 从零实现属于你的 redis 分布式锁
- Redis集群做法的难点,百万并发客户端「实战」
- 如何优雅的停止一个线程?