2

有没有办法更新内存缓存中的项目并保持其绝对过期策略?

我正在编写一个简单的限制类来检查是否应该限制请求。例如,如果 1 分钟内有 > 5 个请求,则限制。

我将请求数存储在缓存对象中,该对象将在 1 分钟后过期。

每次访问对象时请求的数量都会增加,但我无法弄清楚如何在不重新插入新的绝对过期时间的情况下将对象放回缓存中。

有没有办法在不重新插入的情况下更新对象?

例如:

''' <summary>
''' Methods and properties related to throttling requests.
''' </summary>
''' <remarks>
''' Data is persisted to the Local cache and need not be consistant across web farm or web garden environment.
''' </remarks>
Public Class Throttle

    Private Property CacheKey As String
    Private Property CacheObject As Object
    Public Property ThrottleCounter As Integer

    Public Sub New()

        'set the cache key:
        Me.CacheKey = String.Format("Throttle_{0}", userID)

        IncrementThrottle()
    End Sub

    Private Sub IncrementThrottle()
        'get existing cache object:
        Me.CacheObject = HttpRuntime.Cache.Item(Me.CacheKey)

        If IsNothing(Me.CacheObject) Then
            'create cache object:
            Me.ThrottleCounter = 0
            HttpRuntime.Cache.Insert(Me.CacheKey, Me.ThrottleCounter, Date.Now.AddMinutes(1), Caching.Cache.NoSlidingExpiration, CacheItemPriority.Low)
        Else
            Try
                Me.ThrottleCounter = Cint(Me.CacheObject)
            Catch ex As Exception
                Me.ThrottleCounter = 0
            End Try
        End If

        Me.ThrottleCounter += 1

        '###########################################################################
        'update item in cache:
        'I want to put the updated value back in the cache and maintain the absolute expiration.
        '###########################################################################

    End Sub

    ''' <summary>
    ''' Returns True if the request should be throttled.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IsThrottled() As Boolean
        Return Me.ThrottleCounter > 5 
    End Function

End Class
4

1 回答 1

1

我通过创建一个自定义对象来解决这个问题,将 ExpiryDate 值存储在缓存中,然后通过计算当前日期/时间和原始到期日期/时间之间的差异,将对象重新插入到缓存中,并设置一个新的到期日期。

例子:

Public Class Throttle

    Private Property CacheKey As String
    Public Property CacheData As CacheObject

    Public Class CacheObject
        Public RequestCounter As Integer
        Public ExpiryDate As Date
    End Class

    Public Sub New()
        Me.CacheKey = String.Format("Throttle_{0}", userID)
        IncrementThrottle()
    End Sub

    Private Sub IncrementThrottle()
        'get existing cache object:
        Dim cacheObj As Object = HttpRuntime.Cache.Item(Me.CacheKey)

        If Not IsNothing(cacheObj) Then
            Try
                Me.CacheData = CType(cacheObj, CacheObject)
            Catch ex As Exception
                cacheObj = Nothing
            End Try
        End If

        If IsNothing(cacheObj) Then
            'create new cache object:
            Me.CacheData = New CacheObject
            With Me.CacheData
                .RequestCounter = 1
                .ExpiryDate = Date.Now.AddMinutes(1)
            End With

            'insert it to cache:
            HttpRuntime.Cache.Insert(Me.CacheKey, Me.CacheData, Me.CacheData.ExpiryDate, Caching.Cache.NoSlidingExpiration, CacheItemPriority.Low)

        Else
            'calculate the time difference:
            Dim ts As TimeSpan = Date.Now.Subtract(Me.CacheData.ExpiryDate)

            'reinsert item into cache:
            Me.CacheData.RequestCounter += 1
            HttpRuntime.Cache.Insert(Me.CacheKey, Me.CacheData, Date.Now.Subtract(ts), Caching.Cache.NoSlidingExpiration, CacheItemPriority.Low)
        End If

    End Sub

    Public Function IsThrottled() As Boolean
        Return Me.CacheData.RequestCounter > 5
    End Function

End Class
于 2013-11-07T10:26:27.130 回答