其他

10 分钟阅读 967 字 + 499 词
单线程模型
为什么 Redis 是单线程的而不用多线程并行执行充分利用 CPU 呢?
我们要明确的是:Redis 的单线程指的是 Redis 的网络 IO 以及键值对指令读写是由一个线程来执行的。 对于 Redis 的持久化、集群数据同步、异步删除等都是其他线程执行。
至于为啥用单线程,我们先了解多线程有什么缺点。
多线程的弊端
使用多线程,通常可以增加系统吞吐量,充分利用 CPU 资源。
但是,使用多线程后,没有良好的系统设计,可能会出现如下图所示的场景,增加了线程数量,前期吞吐量会增加,再进一步新增线程的时候,系统吞吐量几乎不再新增,甚至会下降!
image-20240915193309572
在运行每个任务之前,CPU 需要知道任务在何处加载并开始运行。也就是说,系统需要帮助它预先设置 CPU 寄存器和程序计数器,这称为 CPU 上下文。
这些保存的上下文存储在系统内核中,并在重新计划任务时再次加载。这样,任务的原始状态将不会受到影响,并且该任务将看起来正在连续运行。
切换上下文时,我们需要完成一系列工作,这是非常消耗资源的操作。
另外,当多线程并行修改共享数据的时候,为了保证数据正确,需要加锁机制就会带来额外的性能开销,面临的共享资源的并发访问控制问题。
引入多线程开发,就需要使用同步原语来保护共享资源的并发读写,增加代码复杂度和调试难度。
单线程又什么好处?
  1. 不会因为线程创建导致的性能消耗;
  2. 避免上下文切换引起的 CPU 消耗,没有多线程切换的开销;
  3. 避免了线程之间的竞争问题,比如添加锁、释放锁、死锁等,不需要考虑各种锁问题。
  4. 代码更清晰,处理逻辑简单。
单线程是否没有充分利用 CPU 资源呢?
官方答案: 因为 Redis 是基于内存的操作,CPU 不是 Redis 的瓶颈 ,Redis 的瓶颈最 有可能是机器内存的大小或者网络带宽 。既然单线程容易实现,而且 CPU 不会成为瓶颈,那就顺理成章地采用单线程的方案了。原文地址: https://redis.io/topics/faq。
redis快的总结
  1. 纯内存操作,一般都是简单的存取操作,线程占用的时间很多,时间的花费主要集中在 IO 上,所以读取速度快。
  2. 整个 Redis 就是一个全局哈希表 ,他的时间复杂度是 O(1),而且为了防止哈希冲突导致链表过长, Redis 会执行 rehash 操作 ,扩充 哈希桶数量,减少哈希冲突。并且防止一次性 重新映射数据过大导致线程阻塞, 采用 渐进式 rehash。巧妙的将一次性拷贝分摊到多次请求过程后总,避免阻塞
  3. Redis 使用的是非阻塞 IO:IO 多路复用,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件 ,Redis 采用自己实现的事件分离器,效率比较高。
  4. 采用单线程模型,保证了每个操作的原子性,也减少了线程的上下文切换和竞争。
  5. Redis 全程使用 hash 结构,读取速度快,还有一些特殊的数据结构, 对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳表,使用有序的数据结构加快读取的速度。
  6. 根据实际存储的数据类型选择不同编码