原創(chuàng)|其它|編輯:郝浩|2009-05-20 10:19:11.000|閱讀 321 次
概述:對于一些小型網(wǎng)站,根本沒有什么人訪問,這種實(shí)現(xiàn)方案完全沒有問題。但是對于訪問量比較大的網(wǎng)站,這種實(shí)現(xiàn)方案,很容易造成數(shù)據(jù)庫over掉。而且在執(zhí)行update的時候,大多數(shù)據(jù)庫默認(rèn)都是使用排它鎖的,這條數(shù)據(jù)是被鎖住的,別人無法使用。訪問量大,被鎖住的機(jī)率也就大了。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
背景:實(shí)現(xiàn)blog網(wǎng)站,每篇文章的點(diǎn)播數(shù)統(tǒng)計(jì)。
簡單實(shí)現(xiàn)方法:文章每次被打開時update一下數(shù)據(jù)庫。如:
Update blog set visitcount=visitcount+1 where blogid=’文章ID’.
當(dāng)然了,對于一些小型網(wǎng)站,根本沒有什么人訪問,這種實(shí)現(xiàn)方案完全沒有問題。但是對于訪問量比較大的網(wǎng)站,這種實(shí)現(xiàn)方案,很容易造成數(shù)據(jù)庫over掉。
而且在執(zhí)行update的時候,大多數(shù)據(jù)庫默認(rèn)都是使用排它鎖的,這條數(shù)據(jù)是被鎖住的,別人無法使用。訪問量大,被鎖住的機(jī)率也就大了。
我的方案:
先把統(tǒng)計(jì)數(shù)據(jù)緩存起來,每N秒鐘寫一次數(shù)據(jù)庫,這樣就大大的減少了數(shù)據(jù)庫的連接次數(shù),以及數(shù)據(jù)被鎖住的機(jī)率。
緩存實(shí)現(xiàn)方案:
定義兩個hashtable(t1,t2)。一個讀一個寫(讀:從client接收數(shù)據(jù)。寫:數(shù)據(jù)寫入數(shù)據(jù)庫)。每隔N秒寫一次數(shù)據(jù)庫。寫數(shù)據(jù)庫的時候最好采用異步的方式進(jìn)行,以防止線程長期占用hashtable(讀).
DEMO:
統(tǒng)計(jì)代碼:VisitStatistic.ashx
在Blog文章頁面中加入標(biāo)簽<script src=” VisitStatistic.ashx”></script>
VisitStatistic.ashx
代碼:
public class VisitStatistic : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
Statistic();
context.Response.Write("");
}
private static object threadLock = new object();
private static Hashtable t1 = Hashtable.Synchronized(new Hashtable());
private static Hashtable t2 = Hashtable.Synchronized(new Hashtable());
private static Timer time = new Timer(WriteToDb, null, 10, 6000);
private static string readtb = "t1";
private static bool isworking = false;
private void Statistic()
{
lock (threadLock)
{
Hashtable ht = WriteTb;
if (ht.ContainsKey(BlogId))
{
ht[BlogId] = (int)ht[BlogId] + 1;
}
else
{
ht.Add(BlogId, 1);
}
}
}
private static void WriteToDb(object obj)
{
if(isworking) return;
isworking = true;
Hashtable tb = ReadTb;
IDictionaryEnumerator enumerator = tb.GetEnumerator();
List<BlogStatistic> items = new List<BlogStatistic >(tb.Count);
while (enumerator.MoveNext())
{
BlogStatistic item = new BlogStatistic () {
VisitCount = (int)enumerator.Value,
BlogId = (int)enumerator.Key
};
items.Add(item);
}
tb.Clear();
if (items.Count > 0)
{
ThreadPool.QueueUserWorkItem(AsynWriteToDb, items);
}
if (readtb == "t1") readtb = "t2";
else readtb = "t1";
isworking = false;
}
private static void AsynWriteToDb(object items)
{
try
{
BlogBusiness business = new BlogBusiness ();
business.AddBlogStatistic((List<BlogStatistic>)items);
}
catch (Exception ex)
{
LogMessage msg = new LogMessage(){
Message = "統(tǒng)計(jì)數(shù)寫入數(shù)據(jù)庫異常"
};
LogHelper.Error(msg, ex);
}
}
private int BlogId
{
get
{
string util = HttpContext.Current.Request["blogid"];
if(string.IsNullOrEmpty(util)
||!Regex.IsMatch(util,@"^"d+$"))
{
HttpContext.Current.Response.End();
}
return int.Parse(util);
}
}
private static Hashtable ReadTb
{
get
{
if (readtb == "t1")
{
return t1;
}
else
{
return t2;
}
}
}
private static Hashtable WriteTb
{
get
{
if (readtb == "t1")
{
return t2;
}
else
{
return t1;
}
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:博客園