网站整站的缓存方式都是依靠的DataSet的ReadXml和WriteXml的方式实现的,这种方式在访问量不是很大的网站中是一点问题都没有的(最大可承受的日IP估计在8000-15000左右),但是当你的网站日IP访问量到达20000时,他就完全崩溃了,出现xml的并发占用问题日趋严重,于是我们就采用了文件流的形式去操作,具体代码如下:
写入:
Stream s = null;
s = File.Open(FileName, FileMode.Create, FileAccess.ReadWrite,FileShare.ReadWrite);
BinaryFormatter b = new BinaryFormatter();
b.Serialize(s, ds);
s.Close();
读取:
Stream s = null;
s = File.Open(FileName, FileMode.Open, FileAccess.Read);
BinaryFormatter b = new BinaryFormatter();
ds = (DataSet)b.Deserialize(s);
s.Close();
这种方式在一定程度上解决了直接使用DataSet的ReadXml和WriteXml的方式带来的问题,但是当网站的日访问量达到40000或更高时,并发问题依然存在,其实存在并发的根本原因不是我们用了什么方式去读取或者写入(方式的不同的确在一定程度上可以解决一些问题,但根本原因没有得到根治),而是在两个或者更多个进程(有需要读取的也有需要写入的)在争抢同一个文件时程序如何给出一个可以让双方满意的方案,于是顺着这个思路,我有对程序做了以下改进:
//读取锁,可以让一个文件被多个进程同时读取,也可以保证只被一个进程改写
ReaderWriterLock locker = new ReaderWriterLock();//读取锁()
写入:
Stream s = null;
try
{
locker.AcquireWriterLock(1500);//写锁定(写入时间最大允许在1500毫秒内完成,超时就立即退出)
if (!File.Exists(FileName))
{
s = File.Create(FileName);
}
else
{
//创建此文件的一个副本,以供同时访问此文件的读取进程使用(就像打印机的复制功能),由于使用了写锁定,其他的写入进程都将转化为读取进程,而读取进程是不存在并发问题的
File.Copy(FileName,FileName.Replace(".xml","Temp.xml"),true);
s = File.Open(FileName, FileMode.Create, FileAccess.ReadWrite,FileShare.ReadWrite);
}
BinaryFormatter b = new BinaryFormatter();
b.Serialize(s, ds);
s.Close();
}
finally
{
if(s!=null)
{
s.Close();
}
locker.ReleaseWriterLock();//释放写锁定
//这里可以加入删除临时文件的代码,但不建议这样做,我测试了下,会产生新的读写并发问题。
}
读取:
Stream s = null;
Stream sTemp = null;
try
{
locker.AcquireReaderLock(1500);//读锁定(当所用文件被写锁定时超时时间为1500毫秒)
s = File.Open(FileName, FileMode.Open, FileAccess.Read);
BinaryFormatter b = new BinaryFormatter();
ds = (DataSet)b.Deserialize(s);
s.Close();
}
catch//这里使用catch主要是因为当读取方法所读的文件正在被改写时会获取空内容导致异常,或者写入超时导致文件内容出错时异常,或者读锁定超时后读取临时文件时刚好临时文件被删除时发生异常
{
locker.ReleaseReaderLock();//释放锁
locker.AcquireReaderLock(1500);//再次锁定
if(File.Exists(FileName.Replace(".xml","Temp.xml")))
{
//读取副本文件
sTemp = File.Open(FileName.Replace(".xml","Temp.xml"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
BinaryFormatter b = new BinaryFormatter();
ds = (DataSet)b.Deserialize(s);
sTemp.Close();
}
}
finally
{
if(s!=null)
{
s.Close();
}
if(sTemp!=null)
{
sTemp.Close();
}
locker.ReleaseReaderLock();
}
转载于:http://blog.csdn.net/zjlovety/article/details/7613094