您的位置:首页 > 其它

简单点播数统计实现方案

2009-05-18 21:39 330 查看
背景:实现blog网站,每篇文章的点播数统计。

简单实现方法:文章每次被打开时update一下数据库。如:

Update blog set visitcount=visitcount+1 where blogid=’文章ID’.

当然了,对于一些小型网站,根本没有什么人访问,这种实现方案完全没有问题。但是对于访问量比较大的网站,这种实现方案,很容易造成数据库over掉。

而且在执行update的时候,大多数据库默认都是使用排它锁的,这条数据是被锁住的,别人无法使用。访问量大,被锁住的机率也就大了。

我的方案:

先把统计数据缓存起来,每N秒钟写一次数据库,这样就大大的减少了数据库的连接次数,以及数据被锁住的机率。

缓存实现方案:

定义两个hashtable(t1,t2)。一个读一个写(读:从client接收数据。写:数据写入数据库)。每隔N秒写一次数据库。写数据库的时候最好采用异步的方式进行,以防止线程长期占用hashtable(读).

DEMO:

统计代码:VisitStatistic.ashx

在Blog文章页面中加入标签<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 = "统计数写入数据库异常"

};

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;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: