[ASP.NET] 如果将缓存“滑动过期时间”设置为1秒会怎样?
2014-04-01 19:09
971 查看
今天编写了一个采用ASP.NET Caching的组件,在为它编写Unit Test的过程中发现了一个有趣的问题,接下来我通过一个简单的实例说明这个问题。我们在一个控制台应用中编写了如下一段程序,这个段程序很简单:我们通过HttpRuntime的静态属性Cache得到表示当前缓存的Cache对象,并调用其Insert方法对当前的时间实施缓存。需要注意的是,我们采用“滑动时间”过期策略,并将这个滑动时间设置为1秒。
class Program
{
static void Main(string[] args)
{
string key = Guid.NewGuid().ToString();
HttpRuntime.Cache.Insert(key, DateTime.Now, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, 1) );
for (int i = 0; i < 5; i++)
{
Console.WriteLine(HttpRuntime.Cache.Get(key)??"N/A");
Thread.Sleep(500);
}
}
}
接下来我们在一个for循环中提取缓存的时间并将其显示在控制台上,每次迭代之后会有0.5秒的休眠时间。根据缓存针对滑动时间过期策略,由于我们每隔0.5秒会读取缓存,所以在这段时间内缓存是不会过期的。但是如下所示的执行结果告诉我们,添加的缓存在1秒之后过期了。
4/1/2014 2:51:12 PM
4/1/2014 2:51:12 PM
N/A
N/A
N/A
是否是ASP.NET缓存机制错了什么问题呢?其实不是,真正的原因是我们将滑动过期时间范围设置得太小了。为了证实这一点,我们按照如下的方式将这个时间设置为2秒。
class Program
{
static void Main(string[] args)
{
string key = Guid.NewGuid().ToString();
HttpRuntime.Cache.Insert(key, DateTime.Now, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, 2) );
for (int i = 0; i < 5; i++)
{
Console.WriteLine(HttpRuntime.Cache.Get(key)??"N/A");
Thread.Sleep(1000);
}
}
}
再次运行我们的程序后会的如下所示的输出结果,我们可以看到添加的缓存并没有过期。
4/1/2014 2:59:15 PM
4/1/2014 2:59:15 PM
4/1/2014 2:59:15 PM
4/1/2014 2:59:15 PM
4/1/2014 2:59:15 PM
通过查看相关源代码,我们发现这个问题的根源所在:如果我们调用Cache的Insert或者Add方法时指定了其slidingExpiration参数,针对该缓存项的每次提取操作,系统都会修改缓存项的过期时间(当前时间+slidingExpiration)。但是过期时间的修改是由前提的:它要求这个slidingExpiration参数指定的时间必须大于设定的最小时间,这个时间对应着内部类型CacheExpires具有如下定义的静态只读属性TimeSpan MIN_UPDATE_DELTA ,我们可以看到它的时间跨度正是1秒。所以如果我们指定的slidingExpiration参数小于1秒,实际上起不到“滑动过期 ”的作用。当然,在真实的项目中我们并不会将滑动时间设置的如此之短。
internal sealed class CacheExpires
{
//其他成员
internal static readonly TimeSpan MIN_UPDATE_DELTA = new TimeSpan(0, 0, 1);
}
class Program
{
static void Main(string[] args)
{
string key = Guid.NewGuid().ToString();
HttpRuntime.Cache.Insert(key, DateTime.Now, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, 1) );
for (int i = 0; i < 5; i++)
{
Console.WriteLine(HttpRuntime.Cache.Get(key)??"N/A");
Thread.Sleep(500);
}
}
}
接下来我们在一个for循环中提取缓存的时间并将其显示在控制台上,每次迭代之后会有0.5秒的休眠时间。根据缓存针对滑动时间过期策略,由于我们每隔0.5秒会读取缓存,所以在这段时间内缓存是不会过期的。但是如下所示的执行结果告诉我们,添加的缓存在1秒之后过期了。
4/1/2014 2:51:12 PM
4/1/2014 2:51:12 PM
N/A
N/A
N/A
是否是ASP.NET缓存机制错了什么问题呢?其实不是,真正的原因是我们将滑动过期时间范围设置得太小了。为了证实这一点,我们按照如下的方式将这个时间设置为2秒。
class Program
{
static void Main(string[] args)
{
string key = Guid.NewGuid().ToString();
HttpRuntime.Cache.Insert(key, DateTime.Now, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, 2) );
for (int i = 0; i < 5; i++)
{
Console.WriteLine(HttpRuntime.Cache.Get(key)??"N/A");
Thread.Sleep(1000);
}
}
}
再次运行我们的程序后会的如下所示的输出结果,我们可以看到添加的缓存并没有过期。
4/1/2014 2:59:15 PM
4/1/2014 2:59:15 PM
4/1/2014 2:59:15 PM
4/1/2014 2:59:15 PM
4/1/2014 2:59:15 PM
通过查看相关源代码,我们发现这个问题的根源所在:如果我们调用Cache的Insert或者Add方法时指定了其slidingExpiration参数,针对该缓存项的每次提取操作,系统都会修改缓存项的过期时间(当前时间+slidingExpiration)。但是过期时间的修改是由前提的:它要求这个slidingExpiration参数指定的时间必须大于设定的最小时间,这个时间对应着内部类型CacheExpires具有如下定义的静态只读属性TimeSpan MIN_UPDATE_DELTA ,我们可以看到它的时间跨度正是1秒。所以如果我们指定的slidingExpiration参数小于1秒,实际上起不到“滑动过期 ”的作用。当然,在真实的项目中我们并不会将滑动时间设置的如此之短。
internal sealed class CacheExpires
{
//其他成员
internal static readonly TimeSpan MIN_UPDATE_DELTA = new TimeSpan(0, 0, 1);
}
相关文章推荐
- 如果将缓存“滑动过期时间”设置为1秒会怎样?
- 滑动过期时间”设置为1秒会怎样
- ASP.NET设置Session过期时间
- ASP.NET设置Session过期时间
- asp.net session过期时间设置
- 如何设置 ASP.NET 页缓存的过期时间值
- C# asp.net IIS 在web.config和IIS中设置Session过期时间
- C# asp.net IIS 在web.config和IIS中设置Session过期时间
- 如何设置 ASP.NET 页缓存的过期时间值
- asp.net web.config 设置Session过期时间
- asp.net web.config 设置Session过期时间
- asp.net web.config 设置Session过期时间
- ahjesus在asp.net中还可以通过设置HttpCookie对象的过期时间为DateTime.MinValue来指定此Cookies为跟随浏览器生效
- 如何设置 ASP.NET 页缓存的过期时间值
- ASP.NET设置Session过期时间
- C# asp.net IIS 在web.config和IIS中设置Session过期时间
- asp.net webconfig session 过期时间设置
- Asp.NET设置Session过期时间的四种方式
- 在ASP.NET中,设置Session的过期时间的方法
- 在ASP.NET中,设置Session的过期时间的方法