`
skydove
  • 浏览: 19383 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

缓存相关问题研究

 
阅读更多

最近研究了缓存工具:memcached跟redis。两者都是基于数据存储在内存中供客户端进行使用的缓存工具。

不同点在于:memcached 的存储方法是一个简单的键/值对,类似于很多语言内的散列或关联数组。通过提供键和值来将信息存储到 memcached 内,通过按特定的键请求信息来恢复信息。

信息会无限期地保留在缓存内,除非发生如下的情况:
  1. 为缓存分配的内存耗尽— 在这种情况下,memcached 使用 LRU(最近最少使用)方法从此缓存删除条目。最近未曾使用的条目会从此缓存中先删除,最旧的最先访问。
  2. 条目被明确删除— 总是可以从此缓存内删除条目。
  3. 条目过期失效— 各条目均有一个有效的期限以便针对此键存储的信息在过于陈旧时可从缓存中清除这些条目。

上述这些情况可以与您应用程序的逻辑综合使用以便确保缓存内的信息是最新的。有了这些基础知识后,让我们来看看在应用程序内如何能最好地利用 memcached。

 Redis内部的数据结构最终也会落实到key-Value对应的形式,不过从暴露给用户的数据结构来看,要比memcached丰富,除了标准的通常意义的键值对,Redis还支持ListSet HashesSorted Set等数据结构

基本命令

Memcached的命令或者说通讯协议非常简单,Server所支持的命令基本就是对特定key的添加,删除,替换,原子更新,读取等,具体包括 Set, Get, Add, Replace, Append, Inc/Dec 等等

 

Memcached的通讯协议包括文本格式和二进制格式,用于满足简单网络客户端工具(如telnet)和对性能要求更高的客户端的不同需求

 

Redis的命令在KVString类型)上提供与Memcached类似的基本操作,在其它数据结构上也支持基本类似的操作(当然还有这些数据结构所特有的操作,如SetunionListpop等)而支持更多的数据结构,在一定程度上也就意味着更加广泛的应用场合

 

除了多种数据结构的支持,Redis相比Memcached还提供了许多额外的特性,比如Subscribe/publish命令,以支持发布/订阅模式这样的通知机制等等,这些额外的特性同样有助于拓展它的应用场景

Redis的客户端-服务器通讯协议完全采用文本格式(在将来可能的服务器间通讯会采用二进制格式)。

事务

redis通过Multi / Watch /Exec等命令可以支持事务的概念,原子性的执行一批命令。在2.6以后的版本中由于添加了对Script脚本的支持,而脚本固有的是以transaction事务的方式执行的,并且更加易于使用,所以不排除将来取消Multi等命令接口的可能性

Memcached的应用模式中,除了increment/decrement这样的原子操作命令,不存在对事务的支持。

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

memcached不保证存储的数据的有效性,Slab内部基于LRU也会自动淘汰旧数据,客户端不能假设数据在服务器端的当前状态,这应该说是MemcachedFeature设定,用户不必太多关心或者自己管理数据的淘汰更新工作,当然是否适合你的应用,取决于具体的需求,它也可能成为你需要精确自行控制Cache生命周期的一个障碍。

Memcached也不做数据的持久化工作,但是有许多基于memcached协议的项目实现了数据的持久化,例如memcacheDB使用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),支持pipelinescript技术

  • 所谓的pipeline就是支持在一次通讯中,发送多个命令给服务器批量执行,带来的代价是服务器端需要更多的内存来缓存查询结果。
  • Redis内嵌了LUA解析器,可以执行lua 脚本,脚本可以通过eval等命令直接执行,也可以使用script load等方式上传到服务器端的script cache中重复使用。

这两种方式都可以有效地减少网络通讯开销,增加数据吞吐率

对于KV的操作,MemcachedRedis都支持MultipleGetSet命令(MemcachedMultiple Set命令貌似只在二进制的协议中支持),这同样有利于性能的提升

实际性能方面,网上有很多测试比较,给出的结果各不相同,这无疑和各种测试的测试用例,测试环境,和测试时具体使用的客户端Library实现有关。但是总体看下来,比较靠谱的结论是在kv类操作上,两者的性能接近,Memcached的结构更加简单,理论上应该会略微快一些。

 

集群

memcached的服务器端互相完全独立,客户端通常通过对键值应用Hash算法决定数据的分区,为了减少服务器的增减对Hash结果的影响,导致大面积的缓存失效,多数客户端实现了一致性hash算法。

Redis计划在服务器端内建对集群的支持,但是目前代码还处于alpha阶段(貌似已经Design了两三年了?)在此之前,同样可以认为每个Redis服务器实例相互之间是完全独立的,需要依靠客户端处理分区算法和可用服务器列表管理的工作。

 

 

Redis官方推荐的用于Sharding的客户端程序库是Twitter的开源项目 Twemproxy, Twemproxy同时支持MemcachedRedis的文本通讯协议。

需要注意的是,Redis的许多命令在集群环境下是不能正确运行的,例如set的交集,以及跨节点的事务操作等等,因为目前的Redis集群设计,根本目标也就是服务器之间互相汇报一下存活状态,以及对数据做荣誉备份平衡负载等而已,本质上对数据的跨节点操作并不提供任何额外支持,所以在数据服务的层面上来说,各个服务器依旧是完全独立的。

这些操作如果一定要实现,当然可以通过客户端代码来实现(效率有多高且不说),类似的问题memcached集群当然也会遇上,但是原本memcached就不支持复杂的操作和数据类型,许多运算逻辑原本就是由客户端代码或应用程序自己处理的。

MR类批处理应用

提供指定范围的遍历操作,是支持类似MapReduce这样的批处理应用逻辑的关键之一,但是要在基于hash方式存储的数据结构的基础上提供这样的支持并不容易(或者说要实现高效的范围或遍历操作并不容易)。

Redis支持Scan操作用于遍历数据集,这一操作基于其内部数据结构及实现的限制,可以保证在Scan开始时的所有数据都能被获取到,但是不能保证不返回重复的数据,这需要由客户端来检查,或者客户端对此无所谓。Scan操作还支持Match条件用来过滤键值,虽然存在一定的局限性,例如match条件的比较是在获取数据之后再执行的,效率是一个问题,更明显的问题是不能保证每次scaniterate过程都能返回同样数量的有效数据。

对于范围操作,RedisOrdered Set支持在插入时指定数据的分数(Score)用于排序,而后支持在指定Score范围内的各种操作,虽然由于不支持基于字符串的或自定义的基准的Range操作,这样的范围操作应用起来有很大的局限性(或者说需要满足特定的应用模式),但是还是比没有好了。

Memcached核心协议本身不支持任何范围类的操作,也没有对遍历操作的支持,甚至不存在官方合法的列举所有Key的操作,这当然很大程度上源于其设计思想和精简的架构

不过还是有一些兼容memcached协议的服务器实现了范围类操作,具体格式可以参考 https://code.google.com/p/memcached/wiki/RangeOps 所建议的标准

此外RedisHashes数据结构,在一定程度上可以满足获取特定子集数据的应用逻辑需求。

综上来说,如果要实现类似HBase支持的scan操作,不论是Redis还是memcached都无法做到,但是对于Redis来说,能否用于批处理类应用,不能一概而论,取决于具体的数据的格式逻辑和使用方式。通过适当的调整应用程序使用数据的方式,还是有可能在一定程度上实现对MR类批处理,或范围查询类应用逻辑的支持的。而对于键值分布在一个较大的连续空间,数量不确定,同时又无法很好的映射为数值进而使用ordered set来处理的这样一些数据结构,应该还是很难高效的分区遍历的。

使用缓存的注意事项

弹性和可用性最常见的一个问题是:“若缓存不可用了,会发生什么情况呢?”缓存内的信息不应该成为信息的的惟一资源。必须要能够从其他位置加载存储在缓存内的数据。如果缓存服务宕掉,应用程序应该回退到从原始数据源加载信息并对信息进行显示所需的格式化。此应用程序还应继续尝试在 缓存内加载和存储信息。一旦 缓存

再次重申,缓存是信息的缓存但并非惟一的数据源。缓存服务器不可用不应该是应用程序的终结,虽然这意味着在 缓存服务器恢复正常之前性能会有所降低。实际上,缓存服务器相对简单,并且虽然不是绝对无故障的,但它的简单性的结果就是它很少会出错。

使用场景:缓存不是数据库,切不可将缓存用作运行应用程序所需信息的惟一信息源;数据应总是可以从其他信息源获取。

 

安全性:为了确保最佳性能,memcached 并未提供任何形式的安全性,没有身份验证,也没有加密。这意味着对 memcached 服务器的访问应该这么处理:一是通过将它们放到应用程序部署环境相同的私有侧,二是如果安全性是必须的,那么就使用 UNIX® socket 并只允许当前主机上的应用程序访问此 memcached 服务器。这多少牺牲了一些灵活性和弹性,以及跨网络上的多台机器共享 RAM 缓存的能力,但这是在目前的情况下确保 memcached 数据安全性的惟一一种解决方案。

分享到:
评论

相关推荐

    缓存替换算法研究综述

    总之,缓存替换算法的研究是一个不断进化的领域,它不仅需要理论上的深入探讨,也需要与实际应用紧密结合,从而确保技术的进步能够转化为系统性能的显著提升。随着信息技术的不断进步,我们可以预见,缓存替换算法的...

    asp.net缓存 缓存

    在这个文档中,我们将深入探讨.NET缓存的不同类型、使用场景以及缓存的优缺点。 首先,我们来看.NET缓存的类型。主要有两种类型的缓存:内存缓存(Application Cache)和输出缓存(Output Cache)。内存缓存主要...

    Hibernate缓存技术研究

    - **缓存失效**:在某些情况下,如数据库数据被其他应用更改时,需要显式地清除相关缓存,以防止数据不一致的问题。 - **缓存刷新**:当使用读写或非严格读写策略时,需要确保在事务结束前调用`session.close()`方法...

    redis本地缓存与redis缓存

    文件名称“RedisCache-master”可能是一个包含Redis缓存相关项目的源代码仓库,里面可能包括了如何配置、使用Redis作为缓存的示例代码,以及如何与本地缓存结合的实践。 总结来说,本地缓存和Redis缓存各有优势,...

    squid缓存服务器的研究

    ### Squid 缓存服务器研究 #### 一、Squid 概述 Squid 是一款广泛应用于互联网数据缓存的开源软件。其主要功能是接收来自客户端的请求,并根据请求内容,从远程服务器获取数据后缓存至本地。当下次再次请求相同的...

    MyBatis缓存(一级缓存、二级缓存)

    在这篇文章中,我们将深入探讨这两个级别的缓存机制及其工作原理。 **一级缓存** 一级缓存是SqlSession级别的缓存,也称为局部缓存。当你执行一个查询后,MyBatis会将结果存储在当前SqlSession的缓存中。如果同一...

    android图片缓存有关的项目

    下面我们将详细探讨图片缓存的相关知识点。 1. 图片缓存的作用: - 减轻网络负载:通过缓存已下载的图片,避免重复下载,节省用户流量和服务器带宽。 - 提升用户体验:快速显示图片,减少因网络延迟导致的等待...

    MySQL缓存研究

    - 监控数据库性能,使用如`SHOW STATUS`命令查看缓存相关指标。 - 实施不同的缓存策略,对比并评估其效果。 - 使用性能分析工具,如MySQL Profiler,进行深入的性能分析。 4. MySQL缓存研究报告 在研究报告中,会...

    Cache 缓存数据和删除缓存的简单示例

    本文将深入探讨Cache缓存数据的原理和实现方法,以及如何有效地管理并删除缓存,以确保高效且响应迅速的应用服务。 首先,我们需要理解什么是缓存。缓存是一种存储技术,用于临时存储经常访问的数据,以减少对主...

    缓存 队列 kettle

    现在,我们来详细探讨一下这些知识点。 **缓存**:缓存是一种存储技术,用于暂时存储经常访问的数据,以便快速响应用户的请求。在IT系统中,缓存可以显著提高性能,减少对主数据库或远程服务的访问压力。常见的缓存...

    分页缓存

    本篇文章将深入探讨如何使用Java来实现分页缓存,并介绍在读取过程中如何优先从缓存获取数据。 首先,理解分页的基本概念是必要的。在Web应用中,当用户浏览大量数据时,通常会采用分页的方式来显示,而不是一次性...

    深入理解Hibernate缓存

    本文详细介绍了Hibernate中的一级缓存和二级缓存,并探讨了如何根据具体应用场景来配置不同的缓存策略。理解并合理利用Hibernate的缓存机制,可以显著提升应用的性能和响应速度。希望本文能够帮助读者更好地掌握...

    IE缓存提取工具

    本文将详细讲解“IE缓存提取工具”及其相关知识点。 1. **浏览器缓存的工作原理** 浏览器缓存主要目的是提高页面加载速度和减少网络带宽的使用。当用户首次访问一个网页时,浏览器会将页面的资源文件下载并存储在...

    hibernate二级缓存实例

    在这个"hibernate二级缓存实例"中,我们将深入探讨二级缓存的原理、配置以及在实际项目中的应用。 首先,我们需要了解一级缓存和二级缓存的区别。一级缓存是Session级别的,每个Session都有自己的一级缓存,用于...

    asp.net缓存更新

    本文将深入探讨ASP.NET缓存管理及其更新策略。 首先,ASP.NET提供两种主要的缓存机制:Application Cache(应用程序缓存)和HttpRuntime.Cache(运行时缓存)。Application Cache主要用于存储全局性、在整个应用...

    Web搜索与Web缓存的若干关键问题研究.rar

    《Web搜索与Web缓存的若干关键问题研究》是一份深入探讨互联网技术核心领域的文档,主要聚焦于两个关键环节:Web搜索和Web缓存。在信息化时代,这两者对于提升用户体验、优化网络性能以及保障信息获取效率至关重要。...

    ASP.NET数据缓存技术

    在这个主题中,我们将深入探讨ASP.NET数据缓存的原理、使用方法以及优化策略。 1. 缓存的基本概念 缓存是一种存储技术,用于暂时存储经常访问的数据,以便快速获取。在ASP.NET中,数据缓存分为两种主要类型:页面...

    nutz 缓存

    4. **缓存事件**:Nutz提供了一些缓存事件监听器,例如在数据更新或删除时,可以触发清除相关缓存的操作,保持缓存与数据库的一致性。 5. **自定义缓存实现**:如果默认的缓存实现不能满足需求,开发者可以通过实现...

    数据缓存案例

    本案例主要关注如何应用缓存来提升应用效率,我们将深入探讨缓存的工作原理、类型以及其在实际项目中的应用。 缓存的工作机制可以简单理解为一个快速查找的中间层,当用户请求数据时,系统首先检查缓存中是否存在所...

Global site tag (gtag.js) - Google Analytics