<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Redis on 文的超级笔记</title>
    <link>/tags/redis/</link>
    <description>Recent content in Redis on 文的超级笔记</description>
    <generator>Hugo -- 0.152.2</generator>
    <language>zh</language>
    <lastBuildDate>Wed, 23 Sep 2026 00:20:00 +0800</lastBuildDate>
    <atom:link href="/tags/redis/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Redis</title>
      <link>/post/tech/%E5%85%AB%E8%82%A1/redis/</link>
      <pubDate>Wed, 23 Sep 2026 00:20:00 +0800</pubDate>
      <guid>/post/tech/%E5%85%AB%E8%82%A1/redis/</guid>
      <description>&lt;h3 id=&#34;为什么需要redis&#34;&gt;为什么需要redis?&lt;/h3&gt;
&lt;p&gt;MySQL 更适合做持久化存储，但数据主要存放在磁盘中，即使有 Buffer Pool 和索引优化，面对高并发、低延迟的访问场景时，性能仍然可能成为瓶颈。为了减少大量请求直接访问数据库，可以在应用和 MySQL 之间增加一层基于内存的高速存储，把经常访问的数据放到内存中，这就是 Redis 最常见的使用场景。&lt;/p&gt;
&lt;p&gt;因此，Redis 的核心价值可以理解为：利用内存提供更快的数据访问速度，承担缓存和高并发读写压力，从而降低 MySQL 的负载。 在此基础上，Redis 还提供了丰富的数据结构、过期机制、持久化、高可用等能力，因此也常被用于计数器、排行榜、分布式锁、消息处理等场景。&lt;/p&gt;
&lt;h3 id=&#34;redis为什么这么快&#34;&gt;Redis为什么这么快&lt;/h3&gt;
&lt;p&gt;Redis 之所以快，最核心的原因是它把主要数据放在&lt;strong&gt;内存&lt;/strong&gt;中。相比磁盘，内存的访问延迟低很多，因此 Redis 的大部分读写操作都不需要等待磁盘 I/O，这一点是它高性能的基础。&lt;/p&gt;
&lt;p&gt;但仅仅把数据放在内存里还不够，Redis 在数据结构和执行模型上也做了很多优化。它为不同场景提供了字符串、哈希、列表、集合、有序集合等数据结构，并针对这些结构设计了高效的底层实现，因此很多常见操作都可以在较低的时间复杂度内完成。&lt;/p&gt;
&lt;p&gt;在命令执行方面，Redis 传统上采用&lt;strong&gt;单线程执行核心命令&lt;/strong&gt;。这样做并不是因为单线程本身一定更快，而是因为 Redis 的主要瓶颈通常不在 CPU，而在网络和内存访问。单线程反而可以避免多线程之间的锁竞争、上下文切换和数据同步问题，让整个执行路径更简单。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Redis 传统上使用单线程执行核心命令，主要不是因为“单线程天然更快”，而是因为 Redis 的大部分操作都是内存访问，单次命令执行时间非常短，系统瓶颈通常并不首先出现在 CPU 计算能力上。
如果让多个线程同时执行 Redis 命令，就会出现多个线程同时读写共享数据结构的情况。为了保证数据正确性，就需要引入锁和其他同步机制。线程之间频繁竞争锁时，CPU 不仅要执行真正的数据操作，还要额外处理加锁、解锁、自旋、阻塞、唤醒、上下文切换以及不同 CPU 核之间的缓存同步。这些工作都会消耗 CPU 时间，但并不会直接提升 Redis 命令的处理结果。而 Redis 本身一次内存操作已经很快，如果命令执行只需要很短时间，那么多线程带来的并行收益可能还没有线程协调的额外开销大。因此，Redis 选择让核心命令按照顺序执行，避免复杂的锁竞争和线程同步，使执行模型保持简单，同时也天然避免了很多并发修改数据带来的问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;所以 Redis 采用单线程核心执行模型，本质上是在做一个权衡：&lt;strong&gt;既然内存操作本身已经足够快，与其通过多线程增加锁竞争和调度成本，不如保持命令执行简单，把高并发连接交给 I/O 多路复用处理。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不过，如果只有一个线程，一个问题马上就会出现：一个线程怎么同时处理成千上万个客户端连接？Redis 通过 &lt;strong&gt;I/O 多路复用&lt;/strong&gt;解决这个问题。操作系统可以同时监听大量连接，哪个连接有数据到达，就通知 Redis 处理哪个连接，而不是为每个连接单独创建一个线程。这样既减少了线程数量，又能同时管理大量客户端。因此，Redis 快并不是由某一个单独因素决定的，而是几个因素共同作用的结果：&lt;strong&gt;以内存作为主要存储介质，使用高效的数据结构，核心命令执行模型简单，同时通过 I/O 多路复用高效处理大量网络连接。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Redis 后来的版本也引入了多线程来处理部分网络 I/O，但核心命令执行仍然尽量保持简单，这样可以继续避免复杂的并发控制问题。&lt;/p&gt;
&lt;h3 id=&#34;数据结构&#34;&gt;数据结构&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;String&lt;/strong&gt; ：最基础的数据类型，可以理解成“一个 key 对应一个值”。这个值既可以是字符串，也可以是数字或二进制数据，因此很适合用来缓存单个对象、保存计数器，或者存储一些简单状态。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hash&lt;/strong&gt; ：可以理解成“一个 key 对应多个字段”。例如一个用户可以包含 &lt;code&gt;name&lt;/code&gt;、&lt;code&gt;age&lt;/code&gt;、&lt;code&gt;email&lt;/code&gt; 等多个属性，所以 Hash 更适合表示一个对象内部的多个字段，而不是把整个对象作为一个完整字符串存进去。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;List&lt;/strong&gt; ：一个有顺序、允许重复的数据集合。因为元素有前后顺序，所以比较适合表示队列、消息列表、时间线这类需要维护顺序的数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set&lt;/strong&gt; ：一个无序且不允许重复的集合。它最重要的特点就是天然去重，因此适合用来保存标签、用户集合，或者进行交集、并集、差集等集合运算，例如共同好友这类场景。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sorted Set(ZSet)：&lt;/strong&gt; 和 Set 类似，同样不允许成员重复，但每个成员还会额外关联一个 &lt;code&gt;score&lt;/code&gt;，Redis 可以根据这个 score 对成员进行排序，因此非常适合排行榜、优先级队列等需要“去重并排序”的场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们平时使用的是 Redis 提供的逻辑数据类型，而 Redis 内部为了节省内存和提高性能，会根据数据规模选择不同的底层编码结构。例如 String 底层会使用 SDS，Hash、List、Sorted Set 在数据较小时可能使用更紧凑的 listpack，而 Sorted Set 在数据量较大时通常会使用哈希表和跳表组合实现。也就是说，Redis 的“数据类型”和“底层数据结构”并不是一一对应的。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
