目录
一、概述
一个冷知识:Redis全称是 REmote DIctionary Server
AWS建议在以下场景选择Memcached:
- 简单数据结构
- 多核多线程的大配置节点部署
- 灵活增减节点
- 缓存对象
在以下场景选择Redis:
- 需要持久化数据
- 丰富的数据结构
- 副本高可用
- 自动故障转移
- Pub/Sub模式
- 备份和恢复
所以在缓存一些简单结构数据(实际上主要是KV形式的),且对数据可靠性要求不高时适合Memcached,由于Memcached的存储模型简单,同时结合其多线程模型,反而会带来比Redis更高的吞吐量。Redis更类似一个内存数据库,甚至支持一定程度的事务(原子操作、乐观锁),Memcache是一个告诉的内存KV缓存系统。
二、Redis核心原理
2.1 IO模型
Redis 收到客户端的处理请求,包括获取(socket 读取)、解析、执行、结果返回(socket 写入)等都是由一个顺序串行的主线程完成,也就是所谓的“单线程”。但严格来说,redis4.0 并不是单线程。除了主线程外,还有后台线程处理一些慢速操作,比如清理脏数据、释放无用连接、删除大key等。
虽然是单线程运行,但依然使用的是典型的Reactor的I/O模式。当Socket可读时,会交给单线程事件分发器一一执行。如下图所示:
图中有事件分发,但都是在主线程中运行:
- 建立连接请求事件,通过 Acceptor 处理,并建立对应的 handler 负责后续业务处理。
- 其他事件,Reactor 会调用对应的 handler 完成 read-> 业务处理 ->write 处理流程,并将结果返回给客户端。
Redis存入数据到内存中,响应时间约为 100 纳秒。对于小数据包,Redis server 可以处理 80000 到 100000 QPS,这也是 redis 处理的极限。对于 80% 的公司来说,单线程 redis 就足够了。但如果需更大的QPS,只能选择分区,多台服务器,但这样会带来更多的复杂性,有些功能也会受限(比如管道),同时从redis本身来看,由于读/写网络的读/写系统调用在redis执行过程中占用了大部分CPU时间,瓶颈主要在于网络的IO消耗。一条有效的优化方向就是:使用多线程,充分利用多核,典型的实现如Memcached。
所以Redis6.0开始引入多线程。
- 可以充分利用服务器CPU资源。目前主线程只能使用一个核心
- 多线程任务可以分担redis同步IO的读写负载
原主线程(单线程)和多线程的工作方式如下:
Redis采用将网络数据读写和协议解析通过多线程的方式来处理,对于命令执行来说,仍然使用单线程操作。
从图中很清楚看到,IO多路复用调度和Redis命令执行依然在主线程中以单线程方式执行,而耗时比较明显的IO读写操作、数据解析操作在多线程中并行执行。
2.2 数据结构模型
三、Memcached核心原理
3.1 IO模型
有两个核心特点:
- 多路复用 I/O 模型
- 多线程模式
多路复用I/O和Redis一致,都是基于操作系统提供的多路复用 I/O 模型(如epoll);Memcached 使用了多线程模式,与Redis的多线程有差异。
主线程主要负责侦听客户端连接,在客户端连接到 Memcached 时,Memcached 接收到来的请求,并把连接 push 到工作线程的 CQ 队列中,并向工作线程发送一个信号,告诉工作线程有新的客户端连接需要处理。
当工作线程收到主线程的信号后,便会把 CQ 队列上的客户端连接注册到 libevent 进行侦听,libevent 会侦听客户端连接的读写请求,病调用相关的回调函数进行处理(Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库)。
主线程和工作线程的职责与Redis相比具有明显的差异,Memcache处理整个请求流程是在多线程模式下进行,主线程只负担了接受连接。
四、性能测试
看一篇中性能对比结果。作者对广泛使用的内存数据库进行了实验,以衡量其性能:
- 完成操作所花费的时间。
- 他们在操作期间使用内存的效率如何。
论文中使用的数据库版本:
Database | Version |
---|---|
Redis | 3.0.7 |
Memcached | 1.4.14 |
写操作,Memcached具有很高的性能表现,Redis性能随着记录数表现出较明显的线性关系。
耗时(ms) | Number of records | |||
---|---|---|---|---|
Database | 1,000 | 10,000 | 100,000 | 1,000,000 |
Redis | 34 | 214 | 1,666 | 14,638 |
Memcached | 23 | 100 | 276 | 2,813 |
读操作,Redis性能更高并且比较稳定,Memcached存在略微增长。
耗时(ms) | Number of records | |||
---|---|---|---|---|
Database | 1,000 | 10,000 | 100,000 | 1,000,000 |
Redis | 8 | 6 | 8 | 8 |
Memcached | 9 | 14 | 14 | 30 |
写操作内存消耗,Redis比Memcached更低。
内存使用(MB) | Number of records | |||
---|---|---|---|---|
Database | 1,000 | 10,000 | 100,000 | 1,000,000 |
Redis | 2.5 | 3.8 | 4.3 | 62.7 |
Memcached | 5.3 | 27.2 | 211 | 264.9 |
五、最后总结
Memcached 是最早流行的开源内存缓存解决方案之一,适用于基本的键值工作负载。但是,如果您在企业中工作,或者只是在寻找功能更丰富、扩展性更好且社区活跃的产品,那么 Redis 是最佳解决方案。