如何比较 Redis 与 Memcached
引
Redis 与 Memcached 的比较相当多,首先我们比较一下他们的介绍。
Memcached:一款完全开源、高性能的、分布式的内存系统;
Redis:一个开源的、Key-Value 型、基于内存运行并支持持久化的 NoSQL 数据库;
可以发现,Memcached 更侧重于高性能内存 / 缓存系统,而 Redis 则支持持久化,主打数据库功能,兼可作缓存系统(性能也很高)。
下面有一个更加详细的比较表
对比参数 | Redis | Memcached |
---|---|---|
类型 | 1. 支持内存 2. 非关系型数据库 |
1. 支持内存 2. key-value 形式 < br />3. 缓存系统 |
数据存储类型 | String、List、Set、Hash、Sort Set | 文本型、二进制型 |
查询操作 | 1. 批量操作 < br />2. 支持事务 < br />3. 每个类型 CRUD 不同 | CRUD 和少量其他命令 |
附加功能 | 1. 发布 / 订阅模式 < br />2. 主从分区 < br />3. 序列化支持 < br />4. 脚本支持 | 多线程服务支持 |
网络模型 | 单进程 IO 复用模型 | 多进程非阻塞 IO 模型 |
事件库 | AeEvent | LibEvent |
持久化支持 | RDB、AOF | 不支持 |
网络模型
Memcached 是多线程非阻塞 IO 复用的网络模型 ,它由负责监听的主线程和子线程 worker 组成。主线程监听网络连接,每当接受到网络请求,将连接描述字传递给 worker 线程进行读写 IO 操作。Memcached 的网络层使用 libevent 封装的事件库。但多线程不可避免地会有缓存一致性和锁等问题,这里面带来了性能损耗。
Redis 是单线程 IO 复用模型 ,自己封装了一个简单的 AeEvent 事件处理框架,主要实现了 epoll, kqueue 和 select,对于单纯只有 IO 操作的业务场景来说,单线程可以将速度优势发挥到最大,但对于一些消耗 CPU 资源的计算性的操作例如 redis 提供的排序和聚合等,单线程模型施加会严重影响整体吞吐量,CPU 计算过程中,整个 IO 调度都是被阻塞的。
我们可以粗略得出结论, 在高并发场景的压力下,多线程非阻塞式 IO 的 Memcached 表现会更加优异。
内存管理机制
Memcached 和 Redis 都是由 C 语言开发,他们都是自主实现内存模型。
Memcached 的内存模式是 Slab Allocation。它有以下几个特点:
- Memcached 存储数据的最小单位是 chunk,这种设计是为了避免内存碎片的问题。chunk 的大小可以通过 Factor 来管理。
Slab 和 Page 用于承装不同尺寸的 chunk。
不同尺寸 chunk 最终进入一个 slab_class 进行管理,便于访问。
数据访问流程,用户在 slab_class 找到合适尺寸的 slab,再通过某种方式找到 chunk,保证数据进入一个合适大小的 chunk 中存储,防止内存浪费。
相对于 Memecached,Redis 的内存管理要相对简单。
Redis 每一个数据块都是根据数据类型和大小来分配,每一块数据的元数据存入内存块头部。分配内存时,redis 调用 malloc 后返回首地址指针 real_ptr
。redis 将内存块的大小 size 存入头部,size 本身所占据的内存大小是固定为 sizeof (typeof (size))。根据这个可以推算存储的数据的内存指针 ret_ptr
。释放内存时,通过 ret_ptr
来推算 real_ptr
再调用 free 函数释放内存。
结论
Memcacehd 预分配内存池,用不同大小的内存单元来管理内存,数据选择合适的内存单元来存储。这样节省了申请 / 释放内存的开销,减少了内存碎片产生,但依然会带来内存空间浪费。Memcached 通过这种方式来最大化内存管理性能,是时间优先策略。
Redis 按需申请内存,Redis 会把带过期时间的数据单独存放在一起,这些数据是临时数据,临时数据会根据缓存过期策略来进行剔除。非临时数据则永远不会剔除。Redis 更好地利用了内存空间,是空间优先策略。
数据一致性
Redis 提供了事务,这种事务并非真正的事务实现。而且这种事务性操作容易造成线程阻塞。Memcached 会返回操作的结果,不会影响其他数据。
集群
Memcached 本身不支持集群,但它可以通过客户端来实现集群操作。它通过客户端上的程序库来封装了对集群服务器访问的接口,使得用户看起来似乎是在操作一个节点。客户端的程序通过 hash 算法来选择 memcached 节点,然后去访问对应的节点。
Redis 支持集群。各个节点之间通过二进制协议进行通信,节点与客户端之间通过 ascii 协议进行通信。
总结
如果业务更加侧重性能的高效性,对持久化要求不高,那么应该优先选择 Memcached。
具体到业务有服务器的实时配置、存储 json 字符串等等。
对持久化有高需求,追求多类型数据支持,选择 Redis。
具体到业务有排行榜类应用、社交关系存储、数据排重等等。