彩笔写网站
好吧,这是我的第一篇随笔。。。本人彩笔,求讨论,求指导,求改正,求不喷
先说一下这个浏览量统计吧,最简单最直接的实现:直接打开页面我就update数据库呗。。。好吧,如果浏览量稍许大怎么办捏,数据库会不会挂,会不会影响页面的打开速度呢,看来不咋靠谱
那么,我们就想到了,是不是可以把浏览量的数据放到内存中呢(反正我是这么想的),反正这玩意实时性也没多大意义。。。嗯,这样的话我就可以定时写入数据库了,貌似有点靠谱,好哒,不管这些了,先整一个再说
代码如下:
1 /// <summary> 2 /// 需要统计的数据类型 3 /// </summary> 4 public enum StatisticsData 5 { 6 Person, 7 Event, 8 Place, 9 Object 10 } 11 /// <summary> 12 /// 需要统计的操作 13 /// </summary> 14 public enum StatisticsOperation 15 { 16 /// <summary> 17 /// 浏览 18 /// </summary> 19 View, 20 /// <summary> 21 /// 支持 22 /// </summary> 23 Support, 24 /// <summary> 25 /// 反对 26 /// </summary> 27 Against, 28 /// <summary> 29 /// 评论 30 /// </summary> 31 Talk 32 } 33 /// <summary> 34 /// 统计单元 35 /// </summary> 36 public class StatisticsUnit 37 { 38 public StatisticsData DataType; 39 public int ID; 40 public int Version;//版本号和ID可视为联合主键 41 public int ViewCount;//浏览增量 42 public int SupportCount;//支持数增量 43 public int AgainstCount;//反对数增量 44 public int TalkCount;//评论数增量 45 46 public bool OverMaxCount 47 { 48 get 49 { 50 //读取配置,判断 51 //如果超过单位时间内的最大增量,则返回true 52 return true; 53 } 54 } 55 56 public void Count(StatisticsOperation operation) 57 { 58 switch (operation) 59 { 60 case StatisticsOperation.View: 61 ViewCount++; 62 break; 63 case StatisticsOperation.Support: 64 SupportCount++; 65 break; 66 case StatisticsOperation.Against: 67 AgainstCount++; 68 break; 69 case StatisticsOperation.Talk: 70 TalkCount++; 71 break; 72 default: 73 break; 74 } 75 } 76 } 77 78 /// <summary> 79 /// 内存中的统计数据集合 80 /// 这种工具式的类,如果要到处new的话,我感觉很恶心,所以使用static,然后用lock保证线程安全 81 /// 比如,我要开一瓶啤酒,我只需要找到瑞士军刀,使用里面的酒瓶起子就可以了,而不是new一个瑞士军刀,然后使用里面的起子 82 /// 不知道我的理解对不对,求讨论,求指导 83 /// </summary> 84 public static class StatisticsSet 85 { 86 private static List<StatisticsUnit> list = new List<StatisticsUnit>(); 87 private static List<StatisticsUnit> tmplist = new List<StatisticsUnit>(); 88 private static DateTime time = DateTime.UtcNow; 89 public delegate void DBOperation(ref List<StatisticsUnit> list); 90 91 /// <summary> 92 /// 当list中存在该记录,则自增统计数据,否则添加 93 /// </summary> 94 /// <param name="Unit"></param> 95 /// <param name="OperationType"></param> 96 public static void Append(StatisticsUnit Unit, StatisticsOperation OperationType) 97 { 98 lock (list) 99 {100 //自增或添加101 StatisticsUnit Query = list.Where(u => u.DataType == Unit.DataType && u.ID == Unit.ID && u.Version == Unit.Version).FirstOrDefault();102 if (Query != null)103 Query.Count(OperationType);104 else105 list.Add(Unit);106 //检测是否已经达到更新数据库的条件并执行相关操作107 if (Monitor.TryEnter(tmplist))108 {109 bool overmaxexist = list.Exists(unit => unit.OverMaxCount);110 if (overmaxexist || time.AddMinutes(30/*配置文件:多长时间更新一次数据库*/) >= DateTime.UtcNow)111 {112 //使用委托和多线程创建无阻塞调用113 DBOperation operation = new DBOperation(WriteDB);114 //AsyncCallback callback = new AsyncCallback(CallBack);115 operation.BeginInvoke(ref tmplist, null, null);116 }117 }118 }119 }120 121 /// <summary>122 /// 根据list生成SQL语句并更新数据库123 /// </summary>124 /// <param name="list"></param>125 private static void WriteDB(ref List<StatisticsUnit> list)126 {127 lock (tmplist)128 {129 tmplist = list.OrderBy(unit => unit.DataType).ThenBy(unit => unit.ID).ToList();130 list.Clear();131 time = DateTime.UtcNow;132 //根据list生成SQL语句并更新数据库133 tmplist.Clear();134 }135 }136 }好吧,其实还有几个问题,求完善,求讨论
既然需要统计的数据类型分为4种,那么要不要把list也分成4个呢,这样的话会不会减少lock的几率,执行的更快一点呢
求讨论,求完善,求指导,各种求。。。
TAG: