-
Notifications
You must be signed in to change notification settings - Fork 22
Redis 与 Memcached
Redis 和 Memcached 是两种最受欢迎的内存中键值数据存储服务。Memcached 的设计颇为简洁,而 Redis 具有多种功能,能够有效应用于各种使用案例
memcached和redis都属于内存(memory)键-值(key-value)数据库
它们都从属于数据库解决方案中的nosql家族
,由于两者都将数据存储在内存中,自然而然,它们都是非常理想的缓存实现方案
redis在功能多样性方面要胜过memcached,虽然强大且更具灵活性,但复杂程度也比memcached更甚
memcached采用客户端-服务器(C/S)的架构,客户端和服务器端的通讯使用自定义的协议标准,只要满足协议格式要求,客户端Library可以用任何语言实现
从用户的角度来说,服务器维护了一个键-值关系的数据表,服务器之间相互独立,互相之间不共享数据也不做任何通讯操作。也就是说,memcached本身不支持分布式扩展。客户端需要知道所有的服务器,并自行负责管理数据在各个服务器间的分配
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自身并不主动定期检查和标记哪些数据需要被淘汰,只有当再次读取相关数据时才检查时间戳,或者当内存不够使用需要主动淘汰数据时进一步检查LRU数据
redis为了减少大量小数据CMD操作的网络通讯时间开销 RTT (Round Trip Time),支持pipeline和script技术
所谓的pipeline就是支持在一次通讯中,发送多个命令给服务器批量执行,带来的代价是服务器端需要更多的内存来缓存查询结果
redis内嵌了LUA解析器,可以执行lua脚本,脚本可以通过eval等命令直接执行,也可以使用script load等方式上传到服务器端的script cache中重复使用
这两种方式都可以有效地减少网络通讯开销,增加数据吞吐率
相对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,因为写内存基本上没有问题