很早以前的一个想法及实现方式,因为当时有过一套系统是使用ASP实现,中间也有过性能优化。在考虑到成本时,只对部分页面进行缓存处理,从而提升性能。

在ASP.NET下面,很容易利用一些static方式来做页面级别缓存效果非常好,而模拟static实现方式是最直接方案。而在ASP平台下除了Application、Session对象是把数据存储在内存当中,以下我分析两种方式的利弊。

Session对象

Session自身是以用户级会话方式,所以把其作为缓存很明显只是对当前用户有效,而页面部分数据其实是所有人都共同拥有的,光这一点很难把Session对象当做页面级缓存存储对象。

并大概会遇到以下几种麻烦点:

  1. 用户级会员,仅对当前用户有效。
  2. 当工作在多进程存在时,命中率是一个问题。
  3. 有效期。
  4. 不存在锁问题。

Application对象

以Session相比较Application是应用级存储空间,换言之,只要存在任何页面都可以调用到,并且不存在工作在多进程无法共享问题。

而接下来我们得考虑数据更新问题,因为这类数据并非一层不变,页面级数据更新大概有两种方式:

  • 程序调度
  • 用户触发

程序调度来对于ASP.NET来说容易得多,利用timer很轻松解决问题。而ASP平台下相对于简单得多只有用户触发和时间点两者结合。

比如我们每10分钟调用一次,缓存数据时记录当前时间,并且当每一次读取数据时对其进行判断是否过期。

因此在这几个问题下面,我封装一个类,大致代码如下:

Class Cls_Cache
    ' 增加
    Public Sub Add(ByVal key, ByVal val, ByVal expire)
        Application.Lock
            Application(key & "_time") = DateAdd("n", expire, Now)
            Application(key) = val
        Application.UnLock
    End Sub

    ' 增加不过期缓存
    Public Sub AddNotExpire(ByVal key, ByVal val)
        Application.Lock
            Application(key) = val
        Application.UnLock
    End Sub

    ' 是否存在
    Public Function Exists(ByVal key)
        Exists = True
        If IsDate(Application(key & "_time")) Then
            ' 过期并做移除处理
            If CDate(Application(key & "_time")) < Now() Then
                Remove(key)
                Exists = False
                Exit Function
            End If
        End If
        Exists = True
    End Function

    ' 获取缓存数据
    Public Function Item(ByVal key)
        If Not Exists(key) Then
            Item = ""
        Else
            Item = Application(key)
        End If
    End Function

    ' 移除
    Public Sub Remove(ByVal key)
        Application.Lock
            Application.Contents.Remove(key & "_time")
            Application.Contents.Remove(key)
        Application.UnLock
    End Sub
End Class

以上并没有做异常处理,弱爆了。而在具体业务逻辑层时,需要做的获取数据,如果数据不存在而读取数据库并重新缓存。

例如:获取点击排行新闻,并且每10分钟自动更新一次。

Function GetHotNews()
    Dim cache, KEY, T
    KEY = "HotNews"
    T = 10
    Set cache = New Cls_Cache
    If Not cache.Exists(KEY) Then
        ' 逻辑处理
        cache.Add KEY, "点击排行新闻"&now(), T
    End If
    GetHotNews = cache.Item(KEY)
End Function

后续

相比较有点繁琐,特别是在代码维护方面,所以我给出个建议。

对于业务逻辑层建议模块化,不建议使用Class来封装大部分业务逻辑,本来目地是页面级缓存,在页面加载时Include到对应的目标文件当中。

以上希望那种还处于ASP时代的朋友有点帮助。