当前位置:首页 » 硬盘大全 » 缓存策略的十大优缺点
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

缓存策略的十大优缺点

发布时间: 2022-06-09 12:08:16

⑴ 高速缓存,内存和硬盘三种储存器各有什么优缺点

高速缓存,有cpu的缓存和硬盘的缓存。都是用于存贮需要马上处理的数据,对寿命和反应、速度有很高的要求。
内存,用于加载硬盘的程序,断电清除记忆,8gb/s传输速度。
固态硬盘,存储资料。容量比较小,但近年来已经有大容量但是很贵。主流240g,传输速度500mb/s.
机械硬盘,存贮资料。容量比较大4t,单碟1t。主流单碟1tb=1000gb=1000,000mb,传输速度200-60mb/s.

⑵ JDBC链接数据库的方法有几种各自的优缺点

它代表最低级别的持久性策略。本地框架各不相同,但大多数有着相似的特征。 大多数 JDBC 解决方案把所有的数据访问包装在数据访问对象中,对象中包装有一个关系表。从那里,您可以把数据留在结果集或者选择把结果集中的每一行映射到一个对象。Java 技术开发人员倾向于映射到轻值对象(light value objects)。一个特殊的替代方案是 Martin Fowler 的有效记录设计模式,这种设计模式提供针对数据表中行的包装程序。每一个有效记录都有访问每一列的方法,以及保存、删除或更新行的方法。 长处 基于JDBC 的解决方案提供良好的控制能力。您要写更多的代码来解决预料中的问题,但是您有访问数据库的所有权利,并且可以让它只做您想要它做的事。纯 JDBC 给予您非常好的灵活性。 弱点 关系数据库和对象并不是一回事 —— 这里有一点分歧。您不得不处理一些面向对象的概念,如继承。您还必须自己管理每一个对象,写查询程序来完成创建、读取、更新或删除操作。如果要提升性能,需要提供您自己的缓存。 总结 对于那些技术不好但了解 sql 的 Java 程序员来说,JDBC 是一个很好的选择。如果您需要更好的访问 SQL 或者在进行批处理计算或报告,那么 JDBC 也能胜任。 变种 有几个框架和工具可以帮助您扩展 JDBC。一些工具,像 Velocity 和 MiddleGen,会生成数据访问对象,给出数据库表的描述。Spring 提供依赖注入和面向方面的编程,这使得服务和依赖关系的集成更加容易。但是总得来说,应用程序结构和策略应该保持一致。 对象关系映射程序 OOP 和关系数据库基于根本不同的基础。通常,很难把两者混合起来。如果您有一个现有的关系模式或一个可能频繁改变的关系模式,那么 ORM 框架也许正是您需要的。大多数的 ORM 试图让您透明地处理对象。您提供一个 POJO,然后,通过使用代码生成(EJB)、字节码操纵(JDO)或反射(Hibernate),框架与持久性相关联。每种技术都有它的长处和弱点,因此大多数的框架使用多种方法来完成工作。 您需要告诉应用程序如何映射数据库表到应用程序的类。您可以用一个独立的 XML 文件或程序代码中的注释来达到目的。这些注释可以采取 Java 5 注释的形式(使用 XDoclet 之类的工具)。如果模式和对象模型不会走到一起,我一般会将代码和配置文件分离。 持久性框架让您从数据库载入一系列的对象。您可以显示它们,或操纵它们并把它们存回到关系数据库。大多数的 ORM 框架提供扩展,比如两级缓存。一般来说,第一级缓存保证事务的完整性,第二级保证跨集群中机器的一致性。尽管有多种实现,但是您应该准确理解缓存策略。 您需要用于管理配置和依赖性的策略。您的应用程序可能需要选择一个事务策略并使用数据源和连接池。正如在前面的章节中所学到的那样,Spring 和 ORM 能很好地为您处理这些问题。这里有一些可用的 ORM。 EJB 企业级 JavaBean 提供两种标准化的持久性策略,EJB 1.x 标准 和 2.x 标准。第二个标准做的更好,但仍然过于复杂。EJB 专家组承认这一事实并将提供第三个标准,即 EJB 3 JSR;但是该标准将对所有的 Java Enterprise Edition (JEE) 用户可用,不仅仅是对 EJB 用户可用。因此,EJB 持久性标准实际上是一条死路,因为新的应用程序想要目标方案接近期望的 JSR 220 标准。 Hibernate Hibernate 很快变成了持久性的事实上的标准。它快速,有效,而且是免费的。因为 Hibernate 让您制定任意的 POJO 持久性,所以它必须有一种方法把持久性关联到一个对象而不必改动代码。Hibernate 主要通过反射来提供透明性,但是它通过动态代理混合在一些运行时字节码操纵中。使用反射,Hibernate 可以在事务完成前后查看对象的状态。如果状态发生改变,Hibernate 可以把它保存到数据库中。代理帮助 Hibernate 实现一些其他的特性,比如懒散加载(lazy loading)。(把动态代理想象成一个坐在目标对象前面的对象,它有一个与目标对象相同的接口。每当您调用某些方法或访问实例变量时,代理都可以自由地调用持久层。) Hibernate 仅支持关系数据库,而且它与 SQL 结合的紧密程度比大多数其他的持久性框架要高。Hibernate 使用类似于 SQL 的查询语言,这种相似性对用户的帮助很大。如果需要,您也可以在 Hibernate 中直接使用 SQL。 像JDO 一样,Hibernate 拥有两级缓存。第一级缓存叫做会话,给您一个存放持久性对象的地方。您可以把对象载入缓存并操纵它们。然后决定何时通过在会话上调用刷新(flush)或提交(commit)来将更改持久存储到数据库中。 Hibernate 帮助您管理关系。如果您定义一个关系,比如雇员属于部门,Hibernate 将对其进行管理。如果您载入一个部门的信息,您可以决定是在载入一个部门时载入所有的雇员信息(热切加载),还是等待载入雇员信息(懒散加载)。 长处 Hibernate 有一个灵活的映射机制。一些场景比其他场景付出更多的努力来映射,但是如果您能在一个关系模式中表示它,那么也许在 Hibernate 中有一种方法来映射到它。Hibernate 的性能比大多数的框架要好而且还在不断提升。文档很优秀,收购 JBoss 后,支持也在改善。JBoss 小组也把 Hibernate 放置在一个合适的位置以抢在竞争者之前实现 JSR 200 持久性标准。 对Hibernate 来说,与其他开放源码框架和商业框架的集成比其他的替代框架要好。一般来说,Spring 与 Hibernate 的集成比与其他任何一个持久性框架的集成要好。 Hibernate 是一个创新的框架。在推动与 SQL 的集成上,它比大多数其他的框架走的更远。它具有一些其他框架不支持的特性,比如会话过滤。还有一支强大的公共和商业开发人员团队为其工作。 弱点 如果您是一家大公司,那么您可能要用不支付许可费来弥补支持上的欠缺。Hibernate 比替代框架更加难以管理。例如,您没有 SolarMetric 的 Kodo JDO 产品提供的丰富的管理控制台。您也没有 Versant 的 JDP 产品提供的丰富的用户界面工具。 最后,Hibernate 不像一些持久性框架那么专业。例如,对于一些边缘情况,比如管理懒散加载,Kodo JDO 有非常好的错误信息和更加可预测的行为。 JDO 如果您想要带持久性框架的 Betamax,JDO 1.x 就足够了 —— 虽然时运似乎在转向 JDO 2,更不用说 JSR 220 持久性标准了。在过去三年左右的时间里,最好的技术持久性框架来自 JDO 社区。JDO 通过字节码增强机制实现了透明性。JDO 2 多少会放松这个限制。 JDO 提供一种叫做 JDO QL 的查询语言。对缓存和提取定义了懒散/热切提取场景的组(可以在每次查询的基础上定义这样的场景),它有正式的性能扩展。JDO 还为分离式处理(detached processing)提供一个模型,以便您能够从一个 JDO 会话(叫做 PersistenceManager)分离一个对象,改变并重新附加该对象。然后数据库应用所有更改。 JDO 还为任意的数据存储提供透明的持久性。在现实世界中,大多数的数据是非关系型的,JDO 自己就能很好地为该社区提供解决方案。 长处 JDO 的各种供应商各有长处。Kodo 产品在需要极限持久性场景的利基市场卖得很好。Kodo 执行快速,并得到广泛的认同:它对任何一个 JDO 产品都有最好的映射支持。(我要说,就现在来看,它的映射支持是业界最好的。)Kodo 还在可管理性方面领先。(Versant 产品也有着非常快的速度。)显然,它的最大优点是针对映射支持的用户界面。 弱点 对JDO 弱点的任何处理都必须从市场份额开始。作为一个标准,JDO 应当得到更好的保护,但是到目前为止,这个标准并不是非常成功。具有讽刺意味的是,JSR 220 持久性标准的出现很可能会对 JDO 造成打击。许多 JDO 供应商已经宣布在他们的产品中支持 JSR 220。您将会看到一个更强大的标准,而且好的 JDO 供应商将能够在那些市场中占有一席之地。JSR 220 标准将会开放,而且新的标准将从那里快速产生,您将会看到顾客使用同样的标准来尝试 JDO。由于疲弱的市场表现, JDO 需要在开放源码社区中更好地表现。Versant 向 Eclipse 小组捐赠它的产品是在正确的方向上前进了一步。 其他 Top Link、OJB 和 Cayenne 正在追赶 Hibernate,但是它们不可能赶上了(出于许多因素)。在接下来的几期文章中,我将用其他的语言如 Ruby 或 Python 来探索几个框架。 混合解决方案 本文将在介绍完一种混合解决方案后结束。大多数的 ORM 解决方案把一个类映射到一个关系数据库模式,而诸如 iBATIS 之类的混合框架则把类映射到一个 SQL 查询的结果。 对于iBATIS,您提供一个 XML 文件,它指定查询和从那些查询到对象的映射。您能得到 ORM 的一些好处,比如一致缓存策略、独立于代码库的 SQL 和限定的关系管理。 长处 iBATIS 还有一些 ORM 框架没有的优点。您有对 SQL 的严格控制的权利,不必担心对象/关系的不匹配,也不必投入几个月来学习一个对象/关系映射框架。 弱点 iBATIS 不会给予您 ORM 所做的一切。您需要编码查询来完成每一次的数据库访问,而不是您自己来完成访问。与数据库的结合更加紧密。并依靠您选择的 SQL 方言。

⑶ 磁盘写入缓存策略开还是关

在一定程度上提高硬盘的读写速度,开启该功能,甚至少有磁盘碎片产生,但有优点必然有缺点,硬盘写入缓存的知名缺点就是突然断电的计算机,不能很好的保证数据的完整性。
Win10启用磁盘写入缓存的方法:
1、首先按Win+X键,或右击开始按钮,在弹出的菜单中点击“设备管理器”;
2、在弹出的硬盘属性窗口中,切换至“策略”项,勾选“启用设备上的写入缓存”,点击确定即可。(如果想关闭此功能,则取消勾选即可)。

⑷ android有哪几种缓存方式,优缺点是什么

二级缓存工作机制。

1.所谓二级缓存实际上并不复杂,当Android端需要获得数据时比如获取网络中的图片,我们首先从内存中查找(按键查找),内存中没有的再从磁盘文件或sqlite中去查找,若磁盘中也没有才通过网络获取。

2.当获得来自网络的数据,就以key-value对的方式先缓存到内存(一级缓存),同时缓存到文件或sqlite中(二级缓存)。注意:内存缓存会造成堆内存泄露,所有一级缓存通常要严格控制缓存的大小,一般控制在系统内存的1/4。

3.网络中的数据是变化的,数据一旦放入缓存中,再取该数据就是从缓存中获得,这样岂不是不能体现数据的变化?在缓存数据时会设置有效时间,比如说30分钟,若超过这个时间数据就失效并释放空间,然后重新请求网络中的数据。

⑸ JAVA几种缓存技术介绍说明

1、TreeCache / JBossCache

JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行JBoss服务器之间 的集群工作。JBossCache能够通过JBoss应用服务或其他J2EE容器来运行一个MBean服务,当然,它也能独立运行。

2、WhirlyCache

Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。

3、SwarmCache

SwarmCache是一个简单且有效的分布式缓存,它使用IP multicast与同一个局域网的其他主机进行通讯,是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。

4、JCache

JCache是个开源程序,正在努力成为JSR-107开源规范,JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。

5、ShiftOne

ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。

⑹ 深度缓存算法的优缺点

深度缓存算法中物体投影到象平面上的次序是任意的,无须将场景中的表面进行排序,物体之间的遮挡关系是通过深度缓存器进行深度比较加以确定的,算法易于实现。
深度缓存算法只能显示距离视点最近的物体,而且这些物体都是不透明的,无法看到被遮挡的物体。
深度缓存算法经常执行一些最终不起作用的中间计算过程。由于对象按任意次序进行处理,因此有些表面进行了颜色计算但事后又被更近的表面所代替。为了缓减这一问题,有些图形软件提供选项让用户调整表面测试的深度范围。例如,通过深度测试排除较远的对象。使用该选项还可以排除非常靠近投影平面的对象。高档计算机图形系统一般集成了深度缓存算法的硬件实现。

⑺ .Net的Cache和Memcached有什么优缺点

如果你的服务器只有一台,且数据库读写压力不大,就没必要使用Memcached。HttpRuntime.Cache是本地缓存,Memcached是分布式缓存,两者的区别在于:

本地缓存
本地缓存可能是大家用的最多的一种缓存方式了,不管是本地内存还是磁盘,其速度快,成本低,在有些场合非常有效。
但是对于web系统的集群负载均衡结构来说,本地缓存使用起来就比较受限制,因为当数据库数据发生变化时,你没有一个简单有效的方法去更新本地缓存;然而,你如果在不同的服务器之间去同步本地缓存信息,由于缓存的低时效性和高访问量的影响,其成本和性能恐怕都是难以接受的。

分布式缓存
前面提到过,本地缓存的使用很容易让你的应用服务器带上“状态”,这种情况下,数据同步的开销09会比较大;尤其是在集群环境中更是如此!
分布式缓存这种东西存在的目的就是为了提供比RDB更高的TPS和扩展性,同时有帮你承担了数据同步的痛苦;优秀的分布式缓存系统有大家所熟知的Memcached、Redis(当然也许你把它看成是NoSQL,但是我个人更愿意把分布式缓存也看成是NoSQL),还有淘宝自主开发的Tair等。
对比关系型数据库和缓存存储,其在读和写性能上的差距可谓天壤之别;就拿淘宝的Tair来说,mdb引擎的单机QPS已在10w以上,ldb的也达到了5w~7w,而集群的性能会更高(目前uic所用的Tair集群QPS高达数十万!)。
所以,在技术和业务都可以接受的情况下,我们可以尽量把读写压力从数据库转移到缓存上,以保护看似强大,其实却很脆弱的关系型数据库。

⑻ 缓存存储与传统存储对比的优缺点有哪些

1.三星暂时没有提供网络查询真伪,包修,生产日期等信息的。
2.三星手机通过序列号串号或者手机版本号等是不能鉴别手机真伪的。众所周知,由于目前市面上克隆机较多,单凭手机串号即IMEI号是无法确定手机真伪。
3.如果要鉴别手机真伪的话,请务必携带上购机发票、包修卡和手机,建议到当地的三星服务中心检测手机是否可以保修,这个是最好也是最为准确的一种方法。

⑼ Redis 和 Memcached 各有什么优缺点,主要的应用场景是什么样的

Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较:

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

2、内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。

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


具体为什么会出现上面的结论,以下为收集到的资料:

1、数据类型支持不同

与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。最为常用的数据类型主要由五种:String、Hash、List、Set和Sorted Set。Redis内部使用一个redisObject对象来表示所有的key和value。redisObject最主要的信息如图所示:

type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:”123″ “456”这样的字符串。只有打开了Redis的虚拟内存功能,vm字段字段才会真正的分配内存,该功能默认是关闭状态的。

1)String

  • 常用命令:set/get/decr/incr/mget等;

  • 应用场景:String是最常用的一种数据类型,普通的key/value存储都可以归为此类;

  • 实现方式:String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr、decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。

  • 2)Hash

  • 常用命令:hget/hset/hgetall等

  • 应用场景:我们要存储一个用户信息对象数据,其中包括用户ID、用户姓名、年龄和生日,通过用户ID我们希望获取该用户的姓名或者年龄或者生日;

  • 实现方式:Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。如图所示,Key是用户ID, value是一个Map。这个Map的key是成员的属性名,value是属性值。这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据。当前HashMap的实现有两种方式:当HashMap的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,这时对应的value的redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

  • 3)List

  • 常用命令:lpush/rpush/lpop/rpop/lrange等;

  • 应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现;

  • 实现方式:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

  • 4)Set

  • 常用命令:sadd/spop/smembers/sunion等;

  • 应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的;

  • 实现方式:set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。

  • 5)Sorted Set

  • 常用命令:zadd/zrange/zrem/zcard等;

  • 应用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。

  • 实现方式:Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

  • 2、内存管理机制不同

    在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。Redis只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。同时由于Redis将内存中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个操作,直到子线程完成swap操作后才可以进行修改。当从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。 这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。

    对于像Redis和Memcached这种基于内存的数据库系统来说,内存管理的效率高低是影响系统性能的关键因素。传统C语言中的malloc/free函数是最常用的分配和释放内存的方法,但是这种方法存在着很大的缺陷:首先,对于开发人员来说不匹配的malloc和free容易造成内存泄露;其次频繁调用会造成大量内存碎片无法回收重新利用,降低内存利用率;最后作为系统调用,其系统开销远远大于一般函数调用。所以,为了提高内存的管理效率,高效的内存管理方案都不会直接使用malloc/free调用。Redis和Memcached均使用了自身设计的内存管理机制,但是实现方法存在很大的差异,下面将会对两者的内存管理机制分别进行介绍。

    Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。Slab Allocation机制只为存储外部数据而设计,也就是说所有的key-value数据都存储在Slab Allocation系统里,而Memcached的其它内存请求则通过普通的malloc/free来申请,因为这些请求的数量和频率决定了它们不会对整个系统的性能造成影响Slab Allocation的原理相当简单。 如图所示,它首先从操作系统申请一大块内存,并将其分割成各种尺寸的块Chunk,并把尺寸相同的块分成组Slab Class。其中,Chunk就是用来存储key-value数据的最小单位。每个Slab Class的大小,可以在Memcached启动的时候通过制定Growth Factor来控制。假定图中Growth Factor的取值为1.25,如果第一组Chunk的大小为88个字节,第二组Chunk的大小就为112个字节,依此类推。

    当Memcached接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的Slab Class,然后通过查询Memcached保存着的该Slab Class内空闲Chunk的列表就可以找到一个可用于存储数据的Chunk。当一条数据库过期或者丢弃时,该记录所占用的Chunk就可以回收,重新添加到空闲列表中。从以上过程我们可以看出Memcached的内存管理制效率高,而且不会造成内存碎片,但是它最大的缺点就是会导致空间浪费。因为每个Chunk都分配了特定长度的内存空间,所以变长数据无法充分利用这些空间。如图 所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了。

    Redis的内存管理主要通过源码中zmalloc.h和zmalloc.c两个文件来实现的。Redis为了方便内存的管理,在分配一块内存之后,会将这块内存的大小存入内存块的头部。如图所示,real_ptr是redis调用malloc后返回的指针。redis将内存块的大小size存入头部,size所占据的内存大小是已知的,为size_t类型的长度,然后返回ret_ptr。当需要释放内存的时候,ret_ptr被传给内存管理程序。通过ret_ptr,程序可以很容易的算出real_ptr的值,然后将real_ptr传给free释放内存。

    Redis通过定义一个数组来记录所有的内存分配情况,这个数组的长度为ZMALLOC_MAX_ALLOC_STAT。数组的每一个元素代表当前程序所分配的内存块的个数,且内存块的大小为该元素的下标。在源码中,这个数组为zmalloc_allocations。zmalloc_allocations[16]代表已经分配的长度为16bytes的内存块的个数。zmalloc.c中有一个静态变量used_memory用来记录当前分配的内存总大小。所以,总的来看,Redis采用的是包装的mallc/free,相较于Memcached的内存管理方法来说,要简单很多。

    3、数据持久化支持

    Redis虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志。而memcached是不支持数据持久化操作的。

    1)RDB快照

    Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。但是一个持续写入的数据库如何生成快照呢?Redis借助了fork命令的 on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。我们可以通过Redis的save指令来配置RDB快照生成的时机,比如配置10分钟就生成快照,也可以配置有1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。

    Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件,这样在任何时候出现故障,Redis的RDB文件都总是可用的。同时,Redis的RDB文件也是Redis主从同步内部实现中的一环。RDB有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的。

    2)AOF日志

    AOF日志的全称是append only file,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令。只有那些会导致数据发生修改的命令才会追加到AOF文件。每一条修改数据的命令都生成一条日志,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有的写操作日志还是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的AOF文件取代老的AOF文件。

    AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的流程。在Redis中对AOF调用write写入后,通过appendfsync选项来控制调用fsync将其写到磁盘上的时间,下面appendfsync的三个设置项,安全强度逐渐变强。

  • appendfsync no 当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。

  • appendfsync everysec 当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。所以结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。

  • appednfsync always 当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。

  • 对于一般性的业务需求,建议使用RDB的方式进行持久化,原因是RDB的开销并相比AOF日志要低很多,对于那些无法忍数据丢失的应用,建议使用AOF日志。

    4、集群管理的不同

    Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,但是全内存毕竟才是其高性能的本质。作为基于内存的存储系统来说,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过了单台机器的物理内存大小,就需要构建分布式集群来扩展存储能力。

    Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。下图给出了Memcached的分布式存储实现架构。当客户端向Memcached集群发送数据之前,首先会通过内置的分布式算法计算出该条数据的目标节点,然后数据会直接发送到该节点上存储。但客户端查询数据时,同样要计算出查询数据所在的节点,然后直接向该节点发送查询请求以获取数据。

    相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。最新版本的Redis已经支持了分布式存储功能。Redis Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,具有线性可伸缩的功能。下图给出Redis Cluster的分布式存储架构,其中节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据的放置策略上,Redis Cluster将整个key的数值域分成4096个哈希槽,每个节点上可以存储一个或多个哈希槽,也就是说当前Redis Cluster支持的最大节点数就是4096。Redis Cluster使用的分布式算法也很简单:crc16( key ) % HASH_SLOTS_NUMBER。

    为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。在Redis Cluster中,每个Master节点都会有对应的两个用于冗余的Slave节点。这样在整个集群中,任意两个节点的宕机都不会导致数据的不可用。当Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。

⑽ 分析将数据放到缓存,XML文件,数据库的优缺点

缓存一般指内存,存放比较常用的需要经常修改的数据比较合适,不适合存放比较大的数据。
XML 数据可以存放一些配置参数,可以表示比较复杂的结构,XML 文件比较小的话还可以,太大的话严重影响系统执行效率。
数据库存放结构化的数据,数据库的缓存机制和查询机制可以非常方便的进行数据检索和更新,在数据安全上数据库做的比较好。
至于优缺点主要看实际应用,合适的就是最好的。