转自: https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961272&idx=1&sn=79ad515b013b0ffc33324db86ba0f834&chksm=bd2d02648a5a8b728db094312f55574ec521b30e3de8aacf1d2d948a3ac24dbf30e835089fa7&scene=21#wechat_redirect
mysql
memcache和redis是互联网分层架构中,最经常使用的KV缓存。很多同窗在选型的时候会纠结,究竟是选择memcache仍是redis。面试
画外音:不鼓励粗暴的实践,例如“memcache提供的功能是redis提供的功能的子集,不用想太多,选redis准没错”。redis
虽然redis比memcache更晚出来,且功能确实也更丰富,但对于一个技术人,了解“因此然”恐怕比“选择谁”更重要一些。sql
何时倾向于选择redis?数据库
业务需求决定技术选型,当业务有这样一些特色的时候,选择redis会更加适合。缓存
复杂数据结构网络
value是哈希,列表,集合,有序集合这类复杂的数据结构时,会选择redis,由于mc没法知足这些需求。数据结构
最典型的场景,用户订单列表,用户消息,帖子评论列表等。多线程
持久化架构
mc没法知足持久化的需求,只得选择redis。
可是,这里要提醒的是,真的使用对了redis的持久化功能么?
千万不要把redis看成数据库用:
(1)redis的按期快照不能保证数据不丢失
(2)redis的AOF会下降效率,而且不能支持太大的数据量
不要指望redis作固化存储会比mysql作得好,不一样的工具作各自擅长的事情,把redis看成数据库用,这样的设计八成是错误的。
缓存场景,开启固化功能,有什么利弊?
若是只是缓存场景,数据存放在数据库,缓存在redis,此时若是开启固化功能:
优势是,redis挂了再重启,内存里可以快速恢复热数据,不会瞬时将压力压到数据库上,没有一个cache预热的过程。
缺点是,在redis挂了的过程当中,若是数据库中有数据的修改,可能致使redis重启后,数据库与redis的数据不一致。
所以,只读场景,或者容许一些不一致的业务场景,能够尝试开启redis的固化功能。
自然高可用
redis自然支持集群功能,能够实现主动复制,读写分离。
redis官方也提供了sentinel集群管理工具,可以实现主从服务监控,故障自动转移,这一切,对于客户端都是透明的,无需程序改动,也无需人工介入。
而memcache,要想要实现高可用,须要进行二次开发,例如客户端的双读双写,或者服务端的集群同步。
可是,这里要提醒的是,大部分业务场景,缓存真的须要高可用么?
(1)缓存场景,不少时候,是容许cache miss
(2)缓存挂了,不少时候能够经过DB读取数据
因此,须要认真剖析业务场景,高可用,是否真的是对缓存的主要需求?
画外音:即时通信业务中,用户的在线状态,就有高可用需求。
存储的内容比较大
memcache的value存储,最大为1M,若是存储的value很大,只能使用redis。
何时倾向于memcache?
纯KV,数据量很是大,并发量很是大的业务,使用memcache或许更适合。
这要从mc与redis的底层实现机制差别提及。
内存分配
memcache使用预分配内存池的方式管理内存,可以省去内存分配时间。
redis则是临时申请空间,可能致使碎片。
从这一点上,mc会更快一些。
虚拟内存使用
memcache把全部的数据存储在物理内存里。
redis有本身的VM机制,理论上可以存储比物理内存更多的数据,当数据超量时,会引起swap,把冷数据刷到磁盘上。
从这一点上,数据量大时,mc会更快一些。
网络模型
memcache使用非阻塞IO复用模型,redis也是使用非阻塞IO复用模型。
但因为redis还提供一些非KV存储以外的排序,聚合功能,在执行这些功能时,复杂的CPU计算,会阻塞整个IO调度。
从这一点上,因为redis提供的功能较多,mc会更快一些。
线程模型
memcache使用多线程,主线程监听,worker子线程接受请求,执行读写,这个过程当中,可能存在锁冲突。
redis使用单线程,虽无锁冲突,但难以利用多核的特性提高总体吞吐量。
从这一点上,mc会快一些。
最后说两点
代码可读性,代码质量
看过mc和redis的代码,从可读性上说,redis是我见过代码最清爽的软件,甚至没有之一,或许简单是redis设计的初衷,编译redis甚至不须要configure,不须要依赖第三方库,一个make就搞定了。
而memcache,多是考虑了太多的扩展性,多系统的兼容性,代码不清爽,看起来费劲。
例如网络IO的部分,redis源码1-2个文件就搞定了,mc使用了libevent,一个fd传过来传过去,又pipe又线程传递的,特别容易把人绕晕。
画外音:理论上,mc只支持kv,而redis支持了这么多功能,mc性能应该高很是多很是多,但实际并不是如此,真的可能和代码质量有关。
水平扩展的支持
不论是mc和redis,服务端集群没有自然支持水平扩展,须要在客户端进行分片,这其实对调用方并不友好。若是能服务端集群可以支持水平扩展,会更完美一些。
相关文章:
说了不少,但愿你们对redis和memcache有了新的认识,哪怕是一点点。