带你走进缓“.NET技术”存世界

  我们搞程序的多多少少都了解点算法。总体来讲,算法是什么?算法就是“时间”和“空间”的互换策略。我们常常考究一个算法的时间复杂度或空间复杂度,如果我们有绝对足够的时间或空间,那么算法就不需要了,可惜这种条件是不存在的,只是在某些情况下相对来说我们不用去考虑其中一个。今天我们讨论的“缓存”,自然就是“用空间换时间”的算法。 缓存就是把一些数据暂时存放于某些地方,可能是内存,也有可能硬盘。总之,目的就是为了避免某些耗时的操作。我们常见的耗时的操作,比如数据库的查询、一些数据的计算结果,或者是为了减轻服务器的压力。其实减轻压力也是因查询或计算,虽然短耗时,但操作很频繁,累加起来也很长,造成严重排队等情况,服务器抗不住)

  概念性的东西暂就不说了,说多了都是故事。现在我们来谈谈各种缓存。

  初学.NET的朋友开始就会接触到DataSet类,云里雾里的看着DataSet的例子程序,也不管是咋回事,用就是了。其实DataSet就是缓存,当我们去读取一段数据集合的时候,如果每读取一条数据就处理一条的话,那么我们的程序和数据库会一直连接着。假如处理一条数据的耗时可以忽略不计,或者只有你一个人使用这个数据库的话,那么数据库一直连着也无所谓,我们写代码完全可以不用DataSet类。但是事实上不耗时不可能的,如果耗时严重的话,就会一直占用这数据库连接,直到我们处理完毕。如果这种查询过多,连接数就会占用过多,而且数据库在某些操作时会锁住表,这就会造成其他的请求等待,会出现查询超时,程序异常等现象。所以,我们必须先把数据拿出来,再对这些数据进行相关的处理,尽早的关闭数据库连接,好让数据库处理其他的请求。 所以,适时地选用DataSet或DataReader是比较重要的(说明:DataReader就是hold住连接的读取方式)。

  你可能会迷惑,不知不觉中使用了缓存(DataSet),这都是.net帮你完成的事。可是,你可能还是不太清楚该如何使用缓存,或者说何时使用缓存。不用着急,我们一一来看。

  上面说过,我们缓存的数据无非就是一些数据库的查询、计算结果和频繁查询。那么,我们在实际开发中会碰到哪些这种数据呢? 其实仔细想想这是非常常见的,比如用户登录后的个人资料,当他每次点击连接后造成页面刷新,我们总不能都要去重新查询数据库吧?我们常常用Session来存储这个人的信息,当他退出系统后我们把Session清理掉,所以Session也是缓存,只不过他也是.NET给我们提供好的类,sorry,我又举了一个你不想看到的例子,哈哈。其实Session是私有化的数据,Session的数据访问必须通过SessionID(详情我就不多言了,大家google下),还不足以说明缓存的意义。如果把这个问题延伸下去,假如我们开发的是一个多用户的Blog系统, 每当我们访问其中一个博客时都要去查询这个博主的资料,假如A和B同时访问一个博客时,最理想的状态就是只查询一次,而不是两个人都去访问数据库!是不是呢?其实。。。是也不是!(故事里的事,说是就是,不是也是;说不是就不是,是也不是。 :)。之所以说不是,是因为假如我们的博客网站每天就几个人访问,而且一直发展不起来,我们就没必要用缓存,因为使用缓存带来了更多的开发复杂度,因为每当我们去更新博主的资料的时候不单单要更新数据库的信息,我们还要去处理缓存。但是如果我们的博客访问量非常大,就像博客园似的,如果再不缓存,那数据库服务器早就Gameover了:),那么现在就来看怎么用缓存的吧。

  .Net Framework提供了现成的缓存类供我们使用,常见的是 System.Web.HttpRuntime.Cache。每当我们去执行 BlogDataProvier.GetBlogInfo()方法时(假定这个方法是我们获取博主信息的方法,顾名思义嘛),需要在查询之前先从缓存获取数据,假如数据不存在的话,再去数据库获取,并且把得到的结果存入缓存,并且返回该结果既可。下面我把这个方法的伪代码写出来,好让从来没用过缓存的朋友大致了解一下。


public class SqlDataProvider
{
public static object GetBlogInfo(string username)
{
//这里是从数据库获取BlogInfo
return null;
}
}

public class BlogDataProvider
{
public static object GetBlogInfo(string username)
{
var cacheKey = "Blog_" + username;
var blog = CacheHelper.Get(cacheKey);
if (blog == null)
{
blog = SqlDataProvider.GetBlogInfo(username);
CacheHelper.Set(cacheKey, blog);
}
return blog;
}
}
public class CacheHelper
{
public static object Get(string key)
{
return System.Web.HttpRuntime.Cache.Get(key);
}
public static void Set(string key, object value)
{
System.Web.HttpRuntime.Cache.Insert(key, value);
}
}

缓存,两个字道出了其实际意义,一个是“存”,我们刚刚存了;另一个是“缓”,暂缓,缓存一般只是用来暂时存储,其命运都会被删除或替换掉,所以缓存有个时效问题。如果你说你的数据永远都不会过期,那么说真的,我建议你直接写在代码里就可以了。 

  上面的例子让我们了解到了HttpCache类。看来我们可以用它来解决绝大部分的缓存问题,主要是公共数据的缓存(所谓公共数据就是你我都可以访问的同一数据)。希望新手朋友捧着MSDN仔细学习该类的用法,真的很重要哦,不是吗?

  开始我们说了“拿空间换时间”,目前只提到了缓存一些频繁查询的情况,牺牲空间缓存时间的明显些的例子有吗?没问题,你看好咯!

  说之前先插一句,我们公司现在在招人,其中一道笔试题是介绍一下List<T>和Dictionary<TKey,TValue>的区别和用途。很遗憾,面试了很多人,只有一个同学回答的到位,其他的说什么的都有。你想好怎么回答了吗?:)如果你看了下面发现和你现在想的一致而且你还需要找一份有挑战的工作的话,给我消息哦。

  其实用List<T>,Dictionary<TKey,TValue>泛型就是用来迷魂人的,哈哈,就会有些同学往泛型上面扯,结果上当咯,我完全可以用ArrayList和Hashtable来问。

  List是什么数据结构?数组!而且是动态的数组,之所以动态就是可以视情况动态申请空间。Dictionary是什么结构?有的同学回答是字典。字典是什么数据结构? 散列表!散列,一听这名字就知道是散开分布的数据表。怎么个“散”法? 自然是按照Key来散,每个Key对应一个Value,所以我们常叫做“键值对”,Key和Value是成对的。我们把Dictionary看作是一个数组,那么每个Key的hash值(什么是hash值?在.net里任何类型都有GetHashCode方法,返回int值,有木有),便是数组的下标,而该数组的元素值就是Value!所以我们在获取Dictionary的某个Key的Value时,速度是非常快的,可以直接通过已知的下标拿到值,这个时间复杂度是O(1)。快不快啊?好快好快。但是,你有木有想到,所有的Key的hash值是按顺序来的吗?显然不是,鬼知道你用的什么key,所以,Dictionary的这个数组很长很长,浪费了很多空位置,所以,那就是 空间 换&n上海企业网站设计与制作bsp;时间。当然GetHashCode的算法不同,Key对应的值的分布也有区别,有的比较紧密有的比较松散,常见的算法比如一致性hash算法。

dictionary的实际内存分布

  如上图所示,dict的分布是不紧凑的,牺牲了很多空间,但可以最快速的找到数据,所以dict或hash或map等,不管什么叫什么类,总之都是hashtable,它们的用途主要就是查询。所以,如果我们把博客按用户名作key缓存起来的话,用户访问博客时都是使用的username,所以我们甚至不需要blogId,就可以拿到博主的信息,根本没走数据库。

  而list这种排列紧凑的数据集合一般用于批处理。当然还有兼顾空间和速度的数据结构,那就是树结构,在查找时不需要所有数据都进行遍历,时间复杂度一般是O(logn),而且空间是紧凑的,采用的是链表结构,而不是紧凑的数组。所以在时间和空间上都不比前两者,但用途却十分广大,我们所用的数据库的索引基本上都是用的树。这样既保证了占用空间小,查询的速度也不慢。

  上面这一段我们介绍了hash表的基本原理,现在我们明白了缓存的优势,在实际的项目使用中,我们除了使用系统提供的Cache类以外,完全可以自己尝试写缓存类,为什么不呢?呵呵。我们把一个变量斯static,然后再public,就等于是全局变量了,我们可以到处访问到他,而且我们还要用dict,因为他足够快!还不快动手去写一个,回来再接着看!

  刚才提到了“缓”字,缓也有不同的策略,比如最常见的按时间缓存,在单位时间内该数据有效,每当访问时都要判断缓存的数据是否过期,再决定Get还是Remove。除了时间策略,还有使用热度策略,由于内存有限,所以我们的缓存也不是无限申请的,是时候限制长度了。限制了长度就意味着有人能进来就得有人要出去。这就是Remove策略。我们可以对所有的缓存打上标记,来标记他的热度,每次添加缓存的时候把热度最低的缓存剔除掉(假如已经达到限制的话)。每次获取缓存的时候给该缓存热度+1。这是多人性化的设计,不是吗上海网站建设? 我上篇博文中已经贴出了这类的代码。有兴趣的朋友给你们个传送门

  我们继续用博客园作例子,我们知道博客园的访问量已经很大了(具体多大,俺不知道,反正以前发表评论经常超时,官方团队解决后还发表博文说咋解决的,结果评论里一大票同学都说怎么不用缓存阿:)。  

  当网站访问量达到一定程度后,一台机器很难处理太多的httprequest,这个时候我们必须使用多台机器。假如你的程序没同时跑在多台机器上的话,你对缓存的理解恐怕不会很深,因为谁都要会这种经历:哎呀 sessio不能分布式阿? 哎呀妈呀,我的缓存不能在两台机器上阿,这可咋整?!

  其实这也不能怪你,要怪就怪微软吧。因为IIS,我们的web程序驻留在一个进程里,每个httprequest会有一个线程来处理,所以你甚至都没用过多线程。害人啊,哈哈。但随着项目经验的增加,特别是大项目的历练后,也没什么了。之所以说是微软的错,是因为人家php阿,ruby阿,人家的服务端(apache,nginx等)都是多进程的。每个httprequest一个进程,总共开几十个进程,处理并发。多进程就意味着数据共享问题,就像我们多台机器的情况一样。 这时候需要借助一个共享缓存进程来供其他的web服务进程来访问获取缓存。 这就是下面要说的 分布式缓存。

  如果说两三年前你不知memcached为何物,或许情有可原,那时候还流行自己写windows service。但现在满世界的NoSQLMongoDB,Memcached,Redis,你再不知道的话,真该说多看看博客吧;看看新技术,你已经落后一个时代了。

  上面提到的这个名词都是玩缓存的主。NoSQL是个新技术,NoSQL DB现在很多种,MongoDB就是一种,MongoDB是介于传统关系型数据库和内存数据库的杂交数据库,现在也算是很热门的数据库。MemCached是著名的分布式缓存服务,而Redis(Remoting Dictionary Service),你懂了吧?!我们的缓存服务器可以用memcached或redis,Memcached是纯内存的,重启进程会丢失所有缓存,而redis可以把数据写到硬盘里,各有各的优点吧。Redis更适合存经过计算过的数据。而且Redis支持丰富的数据类型(list\set\hash\string),这要比memcached更灵活些。 他们都有.net的Driver,还有相关的Example和UnitTest,可以官网下载看看。

  关于Redis的使用可以看代震军大虾的http://www.cnblogs.com/daizhj/archive/2011/02/21/1959511.html 

  随着硬件的发展,内存的不断增加,缓存的应用越来越多,现在各种NoSQL数据库应用而生,我们也要紧跟脚步,学习新的理念。关于NoSQL我这里也不多介绍了,自己搜索。

  其他的缓存,比如页面的缓存(OutputCache)我这里就不作介绍了,缓存其他同学补充。谢谢各位阅读。欢迎大家交流,交流的方式希望是和谐的,最好不要有带味的评论,带来不好的讨论氛围,说错误的希望大家提出。

时间: 2024-07-31 17:06:42

带你走进缓“.NET技术”存世界的相关文章

百度大客户销售部带你走进手游大数据世界

近日,伴着TFC第九届移动娱乐展在北京国际会议中心开幕,引起游戏界又一轮的轰动,各大公司携带自家作品纷纷亮相参展,帅哥与美女齐聚,大佬与干货并存.在此次大会上,作为互联网三大巨头之一的百度得到各大厂商的亲睐.其大客户营销部所发布的营销白皮书也引起了厂商和媒体的密切注. 作为http://www.aliyun.com/zixun/aggregation/31877.html">全球最大的中文搜索引擎,百度覆盖近5亿网民,每日响应搜素请求超过50亿次,已经成为用户覆盖度最高.活跃度最高的数字媒

【阿里云大学LIVE】烧脑,还是末日?1月17日晚8点,阿里云研究院田丰院长带你走进AI的世界,亲密互动可以有~

       [阿里云大学LIVE]又跟大家见面啦,这一期由阿里云研究院田丰院长带大家走进AI的世界,如果您对人工智能有兴趣,有疑问,有想法,请在文章评论中留下,田丰老师将在直播中为您一一解答哦. 前段时间有个美剧特别火,最后两集几乎引起了所有影视相关的大号发文讨论.这就是颠覆我们世界观的<西部世界>.        <西部世界>为我们构建了一个诡谲的机器人乐园,在那里,人类和机器人相互厮杀,人类要奴役机器人,而机器人要窥破思维的秘密,像人一样具有意识,二者的界限在压迫与反抗中逐渐

带你走进神奇的内容世界

摘要: 上次笔者已经提到关于外链的一些渠道以及一些网站SEO过程中碰到的相关的一些外链误区.今天,就让笔者带大家走进神奇的内容世界. 外链与内容的重要性笔者已经不需要再提及,但 上次笔者已经提到关于外链的一些渠道以及一些网站SEO过程中碰到的相关的一些外链误区.今天,就让笔者带大家走进神奇的内容世界. 外链与内容的重要性笔者已经不需要再提及,但是今年以来各种打击外链的措施出台.直接导致总舵站长感叹:现在还有可以发外链的地方么?于是,越来越多的站长把重心放在了网站的内容建设上.那内容到底为什么重要

【阿里云大学LIVE】今晚8点,带你走进人工智能的神秘世界

  [阿里云大学LIVE]今晚8点直播,带你走进人工智能的神秘世界 [阿里云大学LIVE]是阿里云大学推出的一档基于云计算.大数据.人工智能.云安全等主题的直播栏目,挖掘社会热点现象背后的技术.阿里云大学,致力于打造从IT时代向DT时代转型过程中在云计算.大数据.人工智能.云安全等领域一所创新人才工厂.通过校企合作.创新人才中心.创业大学等多种方式,打造从学.到练.到赛.到考.到就业与创业的创新型人才培养的全方位闭环生态链.阿里云大学目前已与200多所高校签署了AUCP普惠计划,提供从科技普惠教

Facebook发布十年战略规划:技术沟通世界

依旧是跑步鞋.灰T恤.蓝便裤,标志性的亮相行头.今天早上的F8开发者大会,当扎克伯格跑上台进行主题演讲时,这个年轻人看起来和十年前并没有太大的区别.在他的身上,看不到多少亿万富豪的豪气与商界领袖的霸气,似乎还是一个普通的二十多岁的小伙子. 虽然扎克伯格没有太大改变,但他一手打造的Facebook却已脱胎换骨.十年前,Facebook只是刚成立两年的2400万美国年轻人的专属网络.而现在,Facebook是一个包括诸多社交产品矩阵.拥有全球近16亿用户的庞大社交集团. 在主题演讲中,扎克伯格发布了

李彦宏:技术改变世界

武严 美国<时代>周刊日前启动了一年一度的100位"全球最具影响力人物"评选并公布了200名候选人名单,百度总裁李彦宏就是入围者之一.这个笃行"把事情做到极致"的天蝎座男人,正带领他的百度团队,朝自己理想的状态飞奔而去. 与众不同的人生轨迹 出生在山西阳泉的李彦宏,家里面有三个姐姐一个妹妹.小时候因为常跟父亲去看戏曲电影,他一度迷上了戏曲,在家里经常把床单系成战裙,拿棍子当枪演练一番.如果长期坚持,李彦宏可能会成为梨园精英:阳泉晋剧团招收学员时,他不但去

绿色公民行动带你走进阿拉善

近日,携程与中国绿化基金会签订的"绿色公民行动带你走进阿拉善"战略合作在内蒙古阿拉善"携程林"正式启动.网友自发通过携程的"碳补偿"活动平台兑换的148800棵梭梭树苗也在活动期间落成.此次活 携程旅行网市场与销售动也是国内首个公 资深副总裁 汤澜益团"走进神谜阿拉善"的第一站. 有中国秘境之称的阿拉善,拥有着丰富的自然资源和浩瀚的大漠风光.但因地处干旱荒漠地带,土地沙化问题十分严重.2011年携程与中国绿化基金会签订&quo

目前5G技术存分歧 测试是试金石

目前,国际5G标准制定前的主体研究工作已基本完成,愿景与需求基本明确.3GPP(第三代合作伙伴计划)将于今年9月启动第一次5G技术研讨会,随后5G标准制定工作将正式启动. 接下来,至少有两三年的时间里,标准制定工作将是全球5G的主要课题.在这个时期里,各国.各企业的产业力量将竭尽全力将自身主导的优势写进标准,除均衡利弊.合纵连横的博弈外,自身的技术也必须要是先进的.拿得出手的,技术验证测试自然而然地成为了证明实力的数据支撑和标准卡位的关键. 标准制定准备就绪 全球权威性组织ITU(国际电信联盟)

一起谈.NET技术,带你走进缓存世界

我们搞程序的多多少少都了解点算法.总体来讲,算法是什么?算法就是"时间"和"空间"的互换策略.我们常常考究一个算法的时间复杂度或空间复杂度,如果我们有绝对足够的时间或空间,那么算法就不需要了,可惜这种条件是不存在的,只是在某些情况下相对来说我们不用去考虑其中一个.今天我们讨论的"缓存",自然就是"用空间换时间"的算法. 缓存就是把一些数据暂时存放于某些地方,可能是内存,也有可能硬盘.总之,目的就是为了避免某些耗时的操作.我们常