Appearance
Redis VS Memcached
1. 与 Memcached 对比
1.1. Redis 支持服务器端的数据操作
Redis 和 Memcached 相比,Redis 拥有更多的数据结构并且支持更丰富的数据操作,通常在 Memcached 里面,你需要将数据拿到客户端来进行类型的修改然后在 set 回去,这样就严重增加了网络 IO 的次数和数据体积。在 Redis 里面,这些操作可以在服务端完成,所以这些复杂的操作就和一般的 GET/SET 一样高效。所以,如果需要缓存能支持更复杂的结构和操作,那么 Redis 是不错的选择。
1.2. 内存使用率
如果使用简单的 key-value 存储的话,Memcached 的内存利用率会更高,而如果 Redis 采用 hash 结构来做 key-value 存储,由于其组合式的压缩,其内存利用率会高于 Memcached。
1.3. 性能
由于 Redis 只使用单核,而 Memcached 可以使用多核,所以平均每一个核上 Redis 在存储小数据时比 Memcached 性能更好。而在 100K 以上的数据中,Memcached 性能要高于 Redis。
1.4. 集群模式
- Memcached 没有原生的集群模式,需要依靠客户端来实现集群中分片写入数据;
- Redis 原生支持 cluster 模式,官方支持 Redis Cluster 集群模式;
1.5. 表格对比
| 对比点 | Memcached | Redis |
|---|---|---|
| 是否支持服务端操作 | 不支持 | 支持 |
| 数据结构类型 | 简单 | 复杂多样 |
| 内存使用率 | 简单 key-value 存储,利用率高 | 采用 hash 结构存储,内存利用率高 |
| 性能 | 存储大数据性能高 | 存储小数据性能高 |
| 集群模式 | 没有原生支持 | 原生支持 cluster 模式 |
2. Redis 的线程模式
要了解 Redis 的线程模式,必须先了解下面几个概念:
2.1. 文件事件处理器
- Redis 是基于 reactor 模式开发了网络事件处理器,这个处理器叫做文件事件处理器(file event Handler)。这个文件事件处理器是单线程的,所以 Redis 才叫做单线程模式,采用 IO 多路复用机制去同时监听多个 socket,根据 socket 上的时间来选择对应的事件处理器来处理这个事件;
- 如果被监听的 socket 准备好执行 accept、read、write、close 等操作的时候,跟操作对应的文件事件就会产生,这个时候文件处理器就会调用之前关联好的的事件处理器来处理这个事件;
- 文件事件处理器是单线程模式运行的,但是通过 IO 多路复用机制监听多个 socket,可以实现高性能的网络通信模型,又可以跟内部其他单线程的模块进行对接,保证了 Redis 内部的线程模型的简单性;
- 文件事件处理器的结构包含四个部分:多个 socket、IO 多路复用程序、文件事件分派器、事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等);
- 多个 socket 可能并发的产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,但是会将 socket 放到一个队列中去处理,每次从队列中取出一个 socket 给事件分派器,事件分派器把 socket 给对应的事件处理器;
- 然后一个 socket 的事件处理完了之后,IO 多路复用程序才会将队列中的下一个 socket 给事件分派器。事件分派器会根据每个 socket 当前产生的事件,来选择对应的事件处理器来处理;
2.2. 文件事件
- 当 socket 变得可读时(比如客户端对 Redis 执行 write 操作,或者 close 操作),或者有新的可以应答的 socket 出现时(客户端 Redis 执行 connect 操作),socket 就会产生一个 AE_READABLE 事件;
- 当 socket 变得可写的时候(客户端对 Redis 执行 read 操作),socket 就会产生一个 AE_WRITABLE 事件;
- IO 多路复用程序可以同时监听 AE_READABLE 和 AE_WRITABLE 两种事件,要是一个 socket 同时产生了这两种事件,那么文件分配器优先处理 AE_READABLE 事件,然后才是 AE_WRITABLE 事件;
2.3. 文件事件分派器
如果是客户端要连接 Redis,那么会为 socket 关联连接应答处理器。 如果是客户端要写数据到 Redis,那么会为 socket 关联命令请求处理器。 如果是客户端要从 Redis 读数据,那么会为 socket 关联命令回复处理器。
Redis 内存模式简单示意图:

2.4. 客户端与 Redis 通信的一次流程
- 在 Redis 启动初始化的时候,Redis 会将连接应答处理器跟 AE_READABLE 事件关联起来,接着如果一个客户端跟 Redis 发起连接,此时 Redis 会产生一个 AE_READABLE 事件,然后由连接应答处理器来处理跟客户端建立连接,创建客户端响应的 socket,同时将这个 socket 的 AE_READABLE 事件跟命令请求处理器关联起来;
- 当客户端向 Redis 发起请求的时候(不管是读请求还是写请求,都一样),首先就会在 socket 产生一个 AE_READABLE 事件,然后由对应的命令请求处理器来处理。这个命令请求处理器就会从 socket 中读取请求的相关数据,然后执行操作和处理;
- 接着 Redis 这边准备好了给客户端的响应数据之后,就会将 socket 的 AE_WRITABLE 事件跟命令回复处理器关联起来,当客户端这边准备好读取相应数据时,就会在 socket 上产生一个 AE_WRITABLE 事件,会由相应的命令回复处理器来处理,就是将准备好的响应数据写入 socket,供客户端读取;
- 命令回复处理器写完之后,就会删除这个 socket 的 AE_WRITABLE 事件和命令回复处理器的关联关系;
Redis 通信过程:

3. 为什么单线程 Redis 还可以支撑高并发
- 纯内存操作;
- 核心是基于非阻塞的 IO 多路复用机制;
- 单线程避免了多线程上下文切换的开销;