转载使用缓存的9大误区(下)

author author     2022-09-03     404

关键词:

本文在《使用缓存的9大误区(上)》的基础上继续讨论了使用缓存的几个误区,包括:缓存大量的数据集合,而读取其中一部分;缓存大量具有图结构的对象导致内存浪费;缓存应用程序的配置信息;使用很多不同的键指向相同的缓存项;没有及时的更新或者删除再缓存中已经过期或者失效的数据。


缓存大量的数据集合,而读取其中一部分


  在很多时候,我们往往会缓存一个对象的集合,但是,我们在读取的时候,只是每次读取其中一部分。 我们举个例子来说明这个问题(例子可能不是很恰当,但是足以说明问题)。

  在购物站点中,常见的操作就是查询一些产品的信息,这个时候,如果用户输入了“25寸电视机”,然后查找相关的产品。这个时候,在后台,我们可以查询数据库,找到几百条这样的数据,然后,我们将这几百条数据作为一个缓存项缓存起来,代码的代码如下:

myCache["25products"] =products;

   同时,我们对找出的产品进行分页的显示,每次展示10条。其实在每次分页的时候,我们都是根据缓存的键去获取数据,然后选择下一个10条数据,然后显示。  

   如果是使用本地内存缓存,那么这可能不是什么问题,如果是采用分布式缓存,问题就来了。下图可以清楚的说明这个过程,如图所示:

  技术分享

  相信大家看完这个图,然后结合之前的讲述应该很清楚了问题所在了:每次都按照缓存键获取全部数据,然后在应用服务器那里反序列化全部数据,但是只是取其中10条。

  这里可以将数据集合再次拆分,分为例如25-0-10-products,25-11-20-products等的缓存项,如下图所示:

  技术分享

  当然,查询和缓存的方式有很多,拆分的方式也有很多,这里这是给出一些常见的问题!

缓存大量具有图结构的对象导致内存浪费

  为了更好的说明这个问题,我们首先看到下面的一个类结构图,如图:

  技术分享

  如果我们要把一些Customer数据缓存起来,这里就可以可能出现两个问题:

  1、由于使用.NET的默认序列化机制,或者没有适当的加入相应Attribute(属性),使得缓存了一些原本不需要缓存的数据。

  2、将Customer缓存的时候,同时,为了更快的获取Customer的Order信息,将Order信息缓存在了另外一个缓存项中,导致同一份数据被缓存两次。


  下面,我们就分别来看看这两个问题。

  首先看到第一个。如果我们使用分布式缓存来缓存一些Customer的信息的时候,如果我们没有自己重新Customer的序列化机制,而是采用的默认的,那么序列化机制在序列化Customer的时候,会将Customer所引用的对象也序列化,然后在序列化被序列化对象中的其他引用对象,最后的结果就是:Customer被序列化,Customer的Order信息被序列化,Order引用的OrderItem被序列化,最后OrderItem引用的Product也会序列化。

  整个对象图全部被序列化了,如果这种情况是我们想要的,那么没有问题;如果不是的,那么,我们就浪费了很多的资源了,解决的方法有两个:第一,自己实现序列化,自己完全控制哪些对象需要序列化,我们前面已经讲过了;第二,如果使用默认的序列化机制,那么在不要需要序列化的对象上面加上[NonSerialized]标记。

  下面,我们看到第二个问题。这个问题主要是由于第一个问题引起的:原本在缓存Customer的时候,已经将Customer的其他信息,例如Order,Product已经缓存了。但是很多的技术人员不清楚这一点,然后又把Customer的Order信息去缓存在其他的缓存项,使用的使用就根据Customer的标识,例如ID去缓存中获取Order信息,如下代码所示:

 

var customer = GetCustomerByName("aqilesharp");

var customer.Orders = GetOrderByCustomer(customer.ID);
cache.Add("Customer",customer);

cache.Add("Orders",orders);

  解决这个问题的方法也比较明显,参看第一个问题的解决方案就可以了!

缓存应用程序的配置信息

  因为缓存是有一套数据失效检测周期的(之前说过,要么是固定时间失效,要么是相对时间失效),所以,很多的技术人员喜欢把一些动态变化的信息保存在缓存中,以充分利用缓存机制的这种特性,其中,缓存程序的配置信息就是其中一个例子。

  因为在应用的中的一些配置,可能会发生变化,最简单的就是数据库连接字符串了,如下代码:

var connectionString = cache.Get("ConnectionString");

  当这样设置之后,每隔一段时间缓存失效之后,就去重新读取配置文件,这时候,可能此时的配置就和之前不一样了,并且其他的地方都可以读取缓存从而进行更新,特别是在多台服务器上面部署同一个站点的时候,有时候,我们没有及时的去修改每个服务器上面的站点的配置文件里面的信息,这个时候如何使用分布式缓存缓存配置信息,只要更新一个站点的配置文件,其他站点就全部修改了,技术人员皆大欢喜。OK,这确实看起来是个不错的方法(在必要的时候可以采用一下),但是,不是所有的配置信息都要保持一样的,而且还要考虑怎样一个情况:如果缓存服务器出了问题,宕机了,那么我们所有使用这个配置信息的站点可能都会出问题。

  建议对于这些配置文件的信息,采用监控的机制,例如文件监控,每次文件发生变化,就重新加载配置信息。


  使用很多不同的键指向相同的缓存项
  我们有时候会遇到这样的一个情况:我们把一个对象缓存起来,用一个键作为缓存键来获取这个数据,之后,我们又通过一个索引作为缓存键来获取这个数据,如下代码所示:

 

var product = GetProduct();

cache["prod"] = product;
//...

cache[i] = product;

 

我们之所以这样写,主要因为我们会以多种方式来从缓存中读取数据,例如在进行循环遍历的时候,需要通过索引来获取数据,例如index++等,而有些情况,我们可能需要通过其他的方式,例如,产品名来获取产品的信息。

 

如果遇到这样的情况,那么就建议将这些多个键组合起来,形成如下的形式:

 

var product = GetProduct();

cache["prod_1"] = product;
//...
var index = 1;

var cacheProduct = cache["prod"+index];

 

另外一个常见的问题就是:相同的数据被缓存在不同的缓存项中,例如,如果用户查询尺寸为36寸的彩电,那么可能有可能一个编号为100的电视产品就在结果中,此时,我们将结果缓存。另外,用户在查找一个生产厂家为TCL的电视,如果编号为100的电视产品又出现在结果中,我们把结果又缓存在另外一个缓存项中。这个时候,很显然,出现了内存的浪费。


对于这样的情况,之前笔者采用的方法就是,在缓存中创建了一个索引列表,如图所示:
技术分享

当然,这其中有很多的细节和问题需要解决,这里就不一一述说,要看各自的应用和情况而定! 也非常欢迎大家提供更好的方法。


没有及时的更新或者删除再缓存中已经过期或者失效的数据

这种情况应该是使用缓存最常见的问题,例如,如果我们现在获取了一个Customer的所有没有处理的订单的信息,然后缓存起来,类似的代码如下:

 

var unProcessedOrders = GetOrders(Orderstatus.Pending);

cache.Add["pengingOrders"]unProcessedOrders;

 

之后,用户的一个订单被处理了,但是缓存还没有更新,那么这个时候,缓存中的数据就已经有问题!当然,我这里只是列举的最简单的场景,大家可以联想自己应用中的其他产品,很有可能会出现缓存中的数据和实际数据库中的不一样。


现在很多的时候,我们已经容忍了这种短时间的不一致的情况。其实对于这种情况,没有非常完美的解决方案,如果要做,倒是可以实现,例如每次修改或者删除一个数据,就去遍历缓存中的所有数据,然后进行操作,但是这样往往得不偿失。另外一个折中的方法就是,判断数据的变化周期,然后尽可能的将缓存的时间变短一点。

使用缓存的9大误区

...果说要对一个站点或者应用程序经常优化,可以说缓存的使用是最快也是效果最明显的方式。一般而言,我们会把一些常用的,或者需要花费大量的资源或时间而产生的数据缓存起来,使得后续的使用更加快速。  如果真要细... 查看详情

数据中台建设的9大误区,你中了几条?

由于不同行业、不同企业的发展程度存在差异,因此会导致不同企业的数据中台的建设起点不同。虽然起点存在差异,但是数据中台的建设应该是一个不断迭代和优化的过程,没有终点。另外,不是每个企业都需... 查看详情

转载掌握http缓存——从请求到响应过程的一切(下)

作者:UlrichKautz 编译:胡子大哈翻译原文:http://huziketang.com/blog/posts/detail?postId=58bd4dd1204d50674934c3b0 英文原文:MasteringHTTPCaching-fromrequesttoresponseandeverything转载请注明出处,保留原文链接以及作者信息 查看详情

guavacache(代码片段)

...内存中保存业务系统的数据处理结果,并且等待下次访问使用。在日长开发有很多场合,有一些数据量不是很大,不会经常改动,并且访问非常频繁。但是由于受限于硬盘IO的性能或者远程网络等原因获取可能非常的费时。会导... 查看详情

j2ee之wildfly实践9--使用infinispan过期缓存

...次实例只适用于同一jvm下,不能进行分布式使用。 (转载请注明来源:cnblogscoder-fang)  在standalone.xml中找到<subsystemxmlns="urn:jboss:domain:infinispan:4.0">,在此节点下加入:<cache-co 查看详情

resttemplate发送get请求使用误区多个参数传值为null(转载)(代码片段)

首先看一下官方文档是怎么描述的,传递多个值的情况(注意例子中用到的@pathParam,一般要用@queryParam)RestTemplate实例@ConfigurationpublicclassRestConfiguration@Bean@ConditionalOnMissingBean(RestOperations.class,RestTemplate.class)publicRest 查看详情

数据中台建设常见的几大误区,如何规避,你需要知道这几点

...数据工具的集合数据工具的集合能有效地提高数据开发和使用的效率,实现让数据易用的目标。建设数据中台的核心目标是为业务中台赋能,提升数据规模化应用的能力,有效地实现数据的价值,支持业务数据化和智能化的需求... 查看详情

数据中台建设常见的几大误区,如何规避,你需要知道这几点

...数据工具的集合数据工具的集合能有效地提高数据开发和使用的效率,实现让数据易用的目标。建设数据中台的核心目标是为业务中台赋能,提升数据规模化应用的能力,有效地实现数据的价值,支持业务数据化和智能化的需求... 查看详情

关于电脑的五大误区,原来是这样!

...,从而损耗闪存的寿命。因此,对于固态+机械硬盘搭配使用的机台,建议系统、缓存和数据文件存放在固态硬盘上,电影、音乐等文档存放在机械硬盘上误区三:笔记本长期插电源使用会影响电池寿命对于经常使用电池的笔记... 查看详情

关于数组array的一些误区

$arr1=array(1,2,3,4);$arr2=array(5,6,7,8,9,10);var_dump($arr1+$arr2);   //输出数组形式的(1,2,3,4,9,10)解析:下标相同的,相加情况下,前面的数组元素保留,后面多出的元素挤进来。 $s=‘12345‘;$s[2];//输出3解析;容易造成认为$s... 查看详情

新冠肺炎地图制作的10大误区

译者按昨晚在知识星球中分享了国外一些媒体使用错误地图故意夸大疫情传播的案例,当时Esri的制图大牛KennethField就痛斥这种误用、滥用地图的行为。今天他连发11条推文,针对目前网络上众多的新冠肺炎地图中存在的... 查看详情

系统性能优化的常见八大误区

转载:http://www.cnblogs.com/yunman/articles/5482129.html一、吞吐量与响应时间  系统的吞吐量反映了一个系统的容量,可承受的负载,很多系统都以这样一个指标来衡量系统的性能。而响应时间往往更容易忽视。我认为吞吐量更多是衡... 查看详情

关于httpget/post请求参数长度最大值的一个理解误区(转载)

1.Get方法长度限制HttpGet方法提交的数据大小长度并没有限制,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。下面就是对各种浏览器和服务器的最大处理能力做一些说明.浏览器/服务器说明Mic... 查看详情

二级缓存(转载)

缓存的作用主要是用来提高hibernate的性能,可以简单的理解成一个map。使用缓存涉及到三个操作:把数据放入缓存、从缓存中取数据、删除缓存中的无效数据。         一、一级缓存   ... 查看详情

转载:分布式缓存的通用方法—《可伸缩服务架构》

  本文节选自《可伸缩服务架构:框架与中间件》第四章《缓存的本质和缓存使用的优秀实践》。 4分布式缓存的通用方法笔者所在的多家互联网公司大量使用了缓存,对分布式缓存的应用可谓遍地开花,笔者曾供职... 查看详情

使用过滤器控制浏览器的缓存时间(转载)

原文地址:http://www.blogjava.net/dashi99/archive/2008/12/30/249207.html HTTP/1.1Cache-Control的理解       网页的缓存是由HTTP消息头中的"Cache-control"来控制的,常见的取值有private、no-cache、max-age、mus 查看详情

转载掌握http缓存——从请求到响应过程的一切(上)

作者:UlrichKautz 编译:胡子大哈翻译原文:http://huziketang.com/blog/posts/detail?postId=58b77935204d50674934c3ad 英文原文:MasteringHTTPCaching-fromrequesttoresponseandeverything转载请注明出处,保留原文链接以及作者信息  查看详情

在不使用 windows 文件缓存的情况下复制文件

】在不使用windows文件缓存的情况下复制文件【英文标题】:Copyafilewithoutusingthewindowsfilecache【发布时间】:2010-09-0802:24:31【问题描述】:有人知道将文件从路径A复制到路径B并抑制Windows文件系统缓存的方法吗?典型用途是将大文... 查看详情