Skip to content

Redis 与 Memcached

L edited this page Jun 10, 2019 · 2 revisions

Redis 和 Memcached 是两种最受欢迎的内存中键值数据存储服务。Memcached 的设计颇为简洁,而 Redis 具有多种功能,能够有效应用于各种使用案例
memcached和redis都属于内存(memory)键-值(key-value)数据库
它们都从属于数据库解决方案中的nosql家族,由于两者都将数据存储在内存中,自然而然,它们都是非常理想的缓存实现方案
redis在功能多样性方面要胜过memcached,虽然强大且更具灵活性,但复杂程度也比memcached更甚

基本架构和思想

memcached

memcached采用客户端-服务器(C/S)的架构,客户端和服务器端的通讯使用自定义的协议标准,只要满足协议格式要求,客户端Library可以用任何语言实现
从用户的角度来说,服务器维护了一个键-值关系的数据表,服务器之间相互独立,互相之间不共享数据也不做任何通讯操作。也就是说,memcached本身不支持分布式扩展。客户端需要知道所有的服务器,并自行负责管理数据在各个服务器间的分配

redis

redis的基本应用模式和上图memcached的基本相似
redis内部的数据结构最终也会落实到key-value对应的形式,不过从暴露给用户的数据结构来看,要比memcached丰富,除了标准的通常意义的键值对,redis还支持List,Set, Hashes,Sorted Set等数据结构

事务

redis通过multi / watch / exec等命令可以支持事务的概念,原子性的执行一批命令。在2.6以后的版本中由于添加了对script脚本的支持,而脚本固有的是以transaction事务的方式执行的,并且更加易于使用,所以不排除将来取消multi等命令接口的可能性
memcached的应用模式中,除了increment/decrement这样的原子操作命令,不存在对事务的支持

数据备份,有效性,持久化等

memcached不保证存储的数据的有效性,slab内部基于LRU也会自动淘汰旧数据,客户端不能假设数据在服务器端的当前状态,这应该说是memcached的feature设定,用户不必太多关心或者自己管理数据的淘汰更新工作,当然是否适合你的应用,取决于具体的需求,它也可能成为你需要精确自行控制cache生命周期的一个障碍
memcached也不做数据的持久化工作,但是有许多基于memcached协议的项目实现了数据的持久化,例如memcache DB使用BerkeleyDB进行数据存储,但本质上它已经不是一个cache server,而只是一个兼容memcached的协议key-valueData Store了
redis可以以master-slave的方式配置服务器,slave节点对数据进行replica备份,slave节点也可以充当read only的节点分担数据读取的工作 redis内建支持两种持久化方案,snapshot快照和AOF增量Log方式。快照顾名思义就是隔一段时间将完整的数据dump下来存储在文件中。AOF增量Log则是记录对数据的修改操作(实际上记录的就是每个对数据产生修改的命令本身),两种方案可以并存,也各有优缺点,具体参见http://redis.io/topics/persistence
以上Redis的数据备份持久化方案等,如果不需要,为了提高性能,也完全可以Disable

性能

memcached

memcached自身并不主动定期检查和标记哪些数据需要被淘汰,只有当再次读取相关数据时才检查时间戳,或者当内存不够使用需要主动淘汰数据时进一步检查LRU数据

redis

redis为了减少大量小数据CMD操作的网络通讯时间开销 RTT (Round Trip Time),支持pipeline和script技术
所谓的pipeline就是支持在一次通讯中,发送多个命令给服务器批量执行,带来的代价是服务器端需要更多的内存来缓存查询结果
redis内嵌了LUA解析器,可以执行lua脚本,脚本可以通过eval等命令直接执行,也可以使用script load等方式上传到服务器端的script cache中重复使用
这两种方式都可以有效地减少网络通讯开销,增加数据吞吐率

如何选择

何时应该使用memcached

相对memcached而言,redis的面世时间更晚且具备更多功能,因此开发人员通常将其视为默认性首选方案。不过有两类特殊场景仍然是memcached的一家天下
首先就是对小型静态数据进行缓存处理,最具代表性的例子就是HTML代码片段。memcached的内部内存管理机制虽然不像redis的那样复杂,但却更具实际效率——这是因为memcached在处理元数据时所消耗的内存资源相对更少。作为memcached所支持的惟一一种数据类型,字符串非常适合用于保存那些只需要进行读取操作的数据,因为字符串本身无需进行进一步处理
除此之外,memcached在横向扩展方面也比redis更具优势。由于其在设计上的思路倾向以及相对更为简单的功能设置,memcached在实现扩展时的难度比redis低得多。不过根据我们了解到的情况,目前已经有多种经过测试且切实有效的方案能够将redis扩展至多台服务器之上

小结

redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较,总体来看还是比较客观的,现总结如下:

性能对比:
由于redis只使用单核,而memcached可以使用多核,所以平均每一个核上redis在存储小数据时比memcached性能更高。而在100k以上的数据中,memcached性能要高于redis,虽然redis最近也在存储大数据的性能上进行优化,但是比起memcached,还是稍有逊色。

内存使用效率对比:
使用简单的key-value存储的话,memcached的内存利用率更高,而如果redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于memcached。另外,memcached使用预分配的内存池的方式,带来一定程度的空间浪费 并且在内存仍然有很大空间时,新的数据也可能会被剔除,而redis使用现场申请内存的方式来存储数据,不会剔除任何非临时数据 redis更适合作为存储而不是cache。

redis支持服务器端的数据操作:
redis相比memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么redis会是不错的选择。

另外,贴一些前辈们使用redis的经验和教训:

要进行master-slave配置,出现服务故障时可以支持切换
在master侧禁用数据持久化,只需在slave上配置数据持久化
物理内存+虚拟内存不足,这个时候dump一直死着,时间久了机器挂掉。这个情况就是灾难
当redis物理内存使用超过内存总容量的3/5时就会开始比较危险了,就开始做swap,内存碎片大
当达到最大内存时,会清空带有过期时间的key,即使key未到过期时间
redis与DB同步写的问题,先写DB,后写redis,因为写内存基本上没有问题

参考资料

memcached redis 对比分析

Clone this wiki locally