面试常问题:Redis与Memcached的区别 ?
网络IO模型
Memcached是多线程,非阻塞IO复用的网络模型,
分为监听主线程和worker
子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe
传递给worker线程,进行读写IO,
网络层使用libevent
封装的事件库,多线程模型可以发挥多核作用,但是引入了cache coherency
和锁的问题,
比如,Memcached
最常用的stats
命令,实际Memcached
所有操作都要对这个全局变量加锁,进行计数等工作,带来了性能损耗。Redis使用单线程的IO复用模型,
自己封装了一个简单的AeEvent
事件处理框架,主要实现了epoll
、kqueue
和select
,
对于单纯只有IO操作来说,单线程可以将速度优势发挥到最大,
但是Redis也提供了一些简单的计算功能,比如排序、聚合等,
对于这些操作,单线程模型实际会严重影响整体吞吐量,CPU计算过程中,整个IO调度都是被阻塞住的。
内存管理方面
Memcached使用预分配的内存池的方式,
使用slab和大小不同的chunk来管理内存,Item根据大小选择合适的chunk存储,
内存池的方式可以省去申请/释放内存的开销,并且能减小内存碎片产生,
但这种方式也会带来一定程度上的空间浪费,并且在内存仍然有很大空间时,新的数据也可能会被剔除Redis使用现场申请内存的方式来存储数据,
并且很少使用free-list
等方式来优化内存分配,会在一定程度上存在内存碎片,
Redis跟据存储命令参数,会把带过期时间的数据单独存放在一起,并把它们称为临时数据,非临时数据是永远不会被剔除的,
即便物理内存不够,导致swap也不会剔除任何非临时数据(但会尝试剔除部分临时数据),这点上Redis更适合作为存储而不是cache。
数据一致性问题
Memcached
提供了cas
命令,可以保证多个并发访问操作同一份数据的一致性问题。Redis
没有提供cas
命令,并不能保证这点,不过Redis提供了事务的功能,可以保证一串命令的原子性,中间不会被任何操作打断。
存储方式及其它方面
Memcached
基本只支持简单的key-value
存储,不支持枚举,不支持持久化和复制等功能Redis
除key/value
之外,还支持list
,set
,sorted set
,hash
等众多数据结构,
提供了KEYS进行枚举操作,但不能在线上使用,如果需要枚举线上数据,Redis提供了工具可以直接扫描其dump文件,枚举出所有数据,Redis还同时提供了持久化和复制等功能。