网络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。
3. 数据一致性问题
Memcached使用cas命令保证多个并发访问操作同一份数据的一致性问题。(memcache所有的命令都是原子的,但是命令序列不是原子的,在memcache 1.2.5之后通过采用gets和cas解决了命令序列不是原子性的问题。gets命令会返回给客户端该item的一个唯一标识,在cas时会将这个唯一标识一同带入到memcached,如果唯一标示一致,写操作成功,修改该唯一标识,如果不一致,写操作失败。)
Redis 并未提供cas命令,但是redis提供了事物功能,可以保证一串命令的原子性。
4 . 存储方面
Memcache 只支持简单的key-value,不支持枚举,不支持持久化和复制。
Redis 除了key-value外,还支持list、set、sorted set、hash等众多value的数据类型结构,提供了keys 进行枚举操作,还提供了持久化和复制的功能
总结:
1. redis使用最佳方式是全部数据 in-memory。
2. redis更多的场景是memcached的替代者。
3. 当需要更多的value数据类型时采用redis更合适。
4. 当存储的数据不能被踢出时,使用redis更合适。