一起谈.NET技术,.Net下的分布式缓存--从Discuz!NT的缓存设计谈起

简介:   最近拜读了代振军同学写的关于Discuz!NT的缓存设计的一篇文章《Discuz!NT 缓存设计简析 [原创]》,颇有些想法,姑且写在这里让大家拍砖吧。  缓存真是个好东西,在大型的系统中可以有效地提升系统的速度,此乃废话就不多说了,在.

  最近拜读了代振军同学写的关于Discuz!NT的缓存设计的一篇文章《Discuz!NT 缓存设计简析 [原创]》,颇有些想法,姑且写在这里让大家拍砖吧。

  缓存真是个好东西,在大型的系统中可以有效地提升系统的速度,此乃废话就不多说了,在.Net 平台下面我把缓存从功用大致分为两类,数据对象缓存和页面输出缓存. 对于数据缓存来讲是由System.Web.Caching.Cache这个类来实现,可以从上下文对象Context.Cache 来获取这个对象的引用.而页面/控件输出缓存则是由.Net环境在运行时依据头部的缓存申明来控制缓存策略. 本文主要论证与数据缓存相关的一些应用与问题.

  文中代同学提到了"无法跨Web园共享数据的问题",虽然提到解决方案就是使用XML文件来存放缓存的键值,这里有一个疑惑,就是.Net的Web园既然是进程独立的又何来共享之说呢,真要是这样的话即便是通过XML文档写入缓存键值缓存的对象也不能同时在两个进程中共享,而这里获得的好处仅是避免了在其它的进程中读到了已在当前进程中失效的“脏”缓存数据,这样的话开几个Web园就会产生几个缓存的对象对系统资源的利用系就比较低了. 如果是用Web场布署的话浪费就更多了,也许是还少有论坛达到这样的规模故不在设计能力的范围中吧.CommunityServer也是使用了这个系统对象,并对它作了一些包装形成了CommunityServer.Components.CSCache这个类,还是不错的,可以在项目中选择使用.

  基于这个类的应注实现还有EnterpriseLibrary的CacheBlock里面的NullBackingStore方式,但是为了满足多进程/服务器共程缓存数据的需求EntLib还提供了将SQL SERVER作为后端存储设备的方案,这样在性能要求不是太严,客户端连接不是太多的情况下也可以使用这种方式.只需要将EntLib 配置为共享数据库分区的工作方式即可,所有的CacheManager实例都有对缓存块的读写权,当然你也可配置为只允许一个实例写,其它的来读.

  那么还有没有更好的办法呢,其实是有的. 不过我很奇怪在.Net平台下居然没有“原生态”的分布式缓存解决方案,也许是俺孤陋寡闻吧,有哪位达人知道的请分享。还好我们有Memcached这东西,它在PHP平台上已经取得了巨大的成功,是优秀的分布式缓存解决方案,可以参看这篇文章 , 大型的站点上应该必不可少吧.有举的同学可以去看看, 另外还想好一个思路, 就是在EntLib的基础上作扩展实现IBackingStore 接口从BaseBackingStore派生一个实现出来,再经由Remoting或者ICE这样的分布式中间件技术应该也可以实现的类似的功能吧.

  用XML作为缓存键的存储方式倒是一个不错的想法,这样在批量移除缓存项的时候就不需要作扫描而直接得到相应的缓存键值,跟分布式缓存作一个整合应当是一个不错的方案。

  好了,让我们再回头看看Discuz!NT在页面缓存上有些什么高招.

  总的说来我是不怎么喜欢.Net2.0提供的页面输出缓存功能,主要是不能手动地控制页面缓存的过期,而使有缓存依赖项似乎也有点不爽。事实上使用数据绑定控件相对来说是比较消耗资源的,同样的数据我用StringBuilder直接拼出来输出速度要快不少,测试代码比较简单我这里就不给了,大家可以自己去测去,Discuz!NT在设计中也大量地采用了这样的方法(怪不得速度这么快呢;))。一般来讲模版被保存后后台会在aspx目录生成对应的页面文件, 比如你有一个页面,上面需要显示一个来访者的姓名,它的伪代码看起来可能是这个样子

  模版文件内容show.html:

 
 
< html >
< body >
Hello, Your name
is <% yourname %>
</ body >
</ html >
生成的文件 show.aspx
templateBuilder.AppendLine(
" <html> " );
templateBuilder.AppendLine(
" <body> " );
templateBuilder.AppendLine(
" Hello, Your name is " + this .yourname);
templateBuilder.AppendLine(
" </body> " );
templateBuilder.AppendLine(
" </html> " );

  这里的this.yourname对应着相应页面后台类里面的一个属性,由程序在运行时进行初始化赋值,这样最后得到的页面执行结果就可以从这个templateBuilder对象的ToString()方法得到, templateBuilder就是一个页面后台类里面的StringBuilder类的实例,最后在页面执行完毕后的OnLoad事件中根据不同的页面类型,如首页,频道首页,内容页等, 使用不同的缓存策略将页面执行结果的HTML代码插入到缓存中,下一个请求进来的时候在进入页面生命周期之前的HttpModule(这里面还包含地址重写功能代码)中判断这个缓存是否有效,直接从内存读取缓存发回客户端.这样速度当然就快了, 页面上看到的执行时间自然是0ms. 不过对于登陆用户来说由于要显示不同的登陆信息所以不能使用匿名的缓存文件版本,所以说一旦你登陆页面才会真正执行一次,但是上面要显示的数据都有独立的缓存项,所以仅仅是重新组装一次页面代码罢了,速度还是比较快的,在官方论坛上看到首页加载时间是15ms, 够快的了.

   愚以为连这个时间其实也是可以再节省节省的. 比如用户登陆信息这部分东西可以生成一段JS, 在向浏览器发出了匿名用户的缓存版本时再判断如果用户登陆了就追加这样一段JS代码,在里面去把相应的HTML替换掉就可以了,也可以使用AJAX技术在客户端去取,这样就解决了已登陆用户和未登陆用户在共享缓存版本上的问题,至少在首页这一级是可以的吧,其它的主要页面不好说应该也差不多,俺对论坛程序的流程不是很了解.

  从另一个角度讲已登陆用户不应该速度比匿名用户还慢吧~~~;

  HOHO,终于完成了,先写这些吧。聊点别的`~~总体上看俺觉得实用的就是最好的,不要说DNT的设计有多烂多烂,层次结构多不合理,代码多不OO,但是在这样一个特定的应用环境下它提供了一种相对灵活和高速的解决的方案,我觉得就是一个正确的选择。量体裁衣做出来的东西虽然可维护可重用性较差还是有它的好处的,俺自己也比较倾向于这种针对性很强的解决方案思路,希望DNT能做得更好~~~正如BlogEngine这样的程序,它几乎将很多的数据都Load到内存里面,数据存储默认的也是XML的存储方式,你很难去讲它是一个糟糕的程序,因为它有特定的应用场景,合适的才是最好的~~~~

  本文基于DNT 2.0 RC1, 不当之处请大家斧正, 谢谢.

相关文章:

.Net下的分布式缓存(2)--实现分布式缓存同步的手段 

.Net下的分布式缓存(3)--如果我们没有缓存会怎么样

目录
相关文章
|
14天前
|
人工智能 开发框架 量子技术
【专栏】.NET 技术:驱动创新的力量
【4月更文挑战第29天】.NET技术,作为微软的开发框架,以其跨平台、开源和语言多样性驱动软件创新。它在云计算、AI/ML、混合现实等领域发挥关键作用,通过Azure、ML.NET等工具促进新兴技术发展。未来,.NET将涉足量子计算、微服务和无服务器计算,持续拓宽软件开发边界,成为创新的重要推动力。掌握.NET技术,对于开发者而言,意味着握有开启创新的钥匙。
|
14天前
|
开发框架 .NET C#
【专栏】理解.NET 技术,提升开发水平
【4月更文挑战第29天】本文介绍了.NET技术的核心概念和应用,包括其跨平台能力、性能优化、现代编程语言支持及Web开发等特性。文章强调了深入学习.NET技术、关注社区动态、实践经验及学习现代编程理念对提升开发水平的重要性。通过这些,开发者能更好地利用.NET构建高效、可维护的多平台应用。
|
14天前
|
机器学习/深度学习 vr&ar 开发者
【专栏】.NET 技术:引领开发新方向
【4月更文挑战第29天】本文探讨了.NET技术如何引领软件开发新方向,主要体现在三方面:1) 作为跨平台开发的先锋,.NET Core支持多操作系统和移动设备,借助.NET MAUI创建统一UI,适应物联网需求;2) 提升性能和开发者生产力,采用先进技术和优化策略,同时更新C#语言特性,提高代码效率和可维护性;3) 支持现代化应用架构,包括微服务、容器化,集成Kubernetes和ASP.NET Core,保障安全性。此外,.NET还不断探索AI、ML和AR/VR技术,为软件开发带来更多创新可能。
|
14天前
|
开发框架 Cloud Native 开发者
【专栏】剖析.NET 技术的核心竞争力
【4月更文挑战第29天】本文探讨了.NET框架在软件开发中的核心竞争力:1) .NET Core实现跨平台与云原生技术的融合,支持多操作系统和容器化;2) 提升性能和开发者生产力,采用JIT、AOT优化,提供C#新特性和Roslyn编译器平台;3) 支持现代化应用架构,包括微服务和容器化,内置安全机制;4) 丰富的生态系统和社区支持,拥有庞大的开发者社区和微软的持续投入。这些优势使.NET在竞争激烈的市场中保持领先地位。
|
4天前
|
消息中间件 缓存 NoSQL
Redis经典问题:缓存雪崩
本文介绍了Redis缓存雪崩问题及其解决方案。缓存雪崩是指大量缓存同一时间失效,导致请求涌入数据库,可能造成系统崩溃。解决方法包括:1) 使用Redis主从复制和哨兵机制提高高可用性;2) 结合本地ehcache缓存和Hystrix限流降级策略;3) 设置随机过期时间避免同一时刻大量缓存失效;4) 使用缓存标记策略,在标记失效时更新数据缓存;5) 实施多级缓存策略,如一级缓存失效时由二级缓存更新;6) 通过第三方插件如RocketMQ自动更新缓存。这些策略有助于保障系统的稳定运行。
132 1
|
7天前
|
存储 消息中间件 缓存
Redis缓存技术详解
【5月更文挑战第6天】Redis是一款高性能内存数据结构存储系统,常用于缓存、消息队列、分布式锁等场景。其特点包括速度快(全内存存储)、丰富数据类型、持久化、发布/订阅、主从复制和分布式锁。优化策略包括选择合适数据类型、设置过期时间、使用Pipeline、开启持久化、监控调优及使用集群。通过这些手段,Redis能为系统提供高效稳定的服务。
|
13天前
|
存储 缓存 NoSQL
【Go语言专栏】Go语言中的Redis操作与缓存应用
【4月更文挑战第30天】本文探讨了在Go语言中使用Redis进行操作和缓存应用的方法。文章介绍了Redis作为高性能键值存储系统,用于提升应用性能。推荐使用`go-redis/redis`库,示例代码展示了连接、设置、获取和删除键值对的基本操作。文章还详细阐述了缓存应用的步骤及常见缓存策略,包括缓存穿透、缓存击穿和缓存雪崩的解决方案。利用Redis和合适策略可有效优化应用性能。
|
16天前
|
存储 缓存 NoSQL
Redis多级缓存指南:从前端到后端全方位优化!
本文探讨了现代互联网应用中,多级缓存的重要性,特别是Redis在缓存中间件的角色。多级缓存能提升数据访问速度、系统稳定性和可扩展性,减少数据库压力,并允许灵活的缓存策略。浏览器本地内存缓存和磁盘缓存分别优化了短期数据和静态资源的存储,而服务端本地内存缓存和网络内存缓存(如Redis)则提供了高速访问和分布式系统的解决方案。服务器本地磁盘缓存因I/O性能瓶颈和复杂管理而不推荐用于缓存,强调了内存和网络缓存的优越性。
43 1
|
2天前
|
缓存 NoSQL 安全
Redis经典问题:缓存击穿
本文探讨了高并发系统中Redis缓存击穿的问题及其解决方案。缓存击穿指大量请求同一未缓存数据,导致数据库压力过大。为解决此问题,可以采取以下策略:1) 热点数据永不过期,启动时加载并定期异步刷新;2) 写操作加互斥锁,保证并发安全并设置查询失败返回默认值;3) 预期热点数据直接加缓存,系统启动时加载并设定合理过期时间;4) 手动操作热点数据上下线,通过界面控制缓存刷新。这些方法能有效增强系统稳定性和响应速度。
54 0
|
3天前
|
缓存 NoSQL 应用服务中间件
Redis多级缓存
Redis多级缓存
8 0