经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
推送算法小结
来源:cnblogs  作者:路过天涯  时间:2018/10/20 15:38:04  对本文有异议

秒杀提醒执行算法分析

  • 秒杀提醒要求:活动开始 前一个小时 提醒一次;活动开始 前五分钟再 提醒一次;提醒记录表存已存有两次提醒时间;

  • 状态为 012 分别表示 未提醒提醒一次提醒两次 。查询只查询01

  • 推送方式采用 微信模板消息 提醒用户,程序编程采用 windows服务 形式进行编程

  • 需要声明全局变量:全局字典dic、程序主方法执行间隔时间(static)TIMER_TIME_MINUTE、SQL查询时间差限值(static)SQL_TIME_MINUTE、模板消息域名(static)WEIXIN_PUBLIC_URL、事务执行出错次数(static)SQLTRAN_ERROR_NUMBER、text日志记录物理路径(static)LOG_PATH、全局执行变量isgoing 默认 true、事务ListsqlList

  • 定时执行主方法,要求全局执行变量 isgoing 为 true 时才执行。

  • 插入倒序查询1000条 此为封装主方法,定时执行

    • SQL条件:两次提醒时间分别与当前时间做差(做or运算)【如差值小于指定数(如:<5)】;状态小于2(做and运算)。*Status<2 and ABS(datediff(MINUTE, GETDATE(), RemindDate1))<=" + SQL_TIME_MINUTE + " or ABS(datediff(MINUTE, GETDATE(), RemindDate2 ))<=" + SQL_TIME_MINUTE + " and Status<2

      • 分别判断状态值,推送模板消息(可新建分装方法直接调用);将状态修改语句写入全局变量事务 sqlList 中(可新建封装方法直接调用);并将 IdkeyOpenIdvalue 插入全局字典 dic;text文档记录推送日志。

    • 执行事务:

      • 100以内随机数模5值为0;声明变量是否执行 tran 、执行记录次数 tranCount

        • 执行变量与记录次数小于 SQLTRAN_ERROR_NUMBER 同真时循环执行事务;

          • 执行成功则将执行变量 tran 改为false,记录数 tranCountSQLTRAN_ERROR_NUMBER;执行结果为 0,自增且增量种子为 1;

          • 执行报错则记录次数自增且增量种子为1;

        • 判断记录次数大于等于 SQLTRAN_ERROR_NUMBER 全局字典 dic 重新new一个

    • 判断全局字典 dic 是否有值,有则赋值全局执行变量 isgoing = false,无则赋值全局执行变量 isgoing = true

 

  1. 1 namespace SeckillRemindService
  2. 2 {
  3. 3 /// <summary>
  4. 4 /// 商城秒杀活动:微信模板消息提醒
  5. 5 /// </summary>
  6. 6 partial class SecKillRemindService : ServiceBase
  7. 7 {
  8. 8 #region 全局属性
  9. 9 private System.Timers.Timer _timer;
  10. 10 private int _Interval;
  11. 11 private FileStream fs;
  12. 12 private StreamWriter sw;
  13. 13 public static int TIMER_TIME_MINUTE = Convert.ToInt32(ConfigurationManager.AppSettings["TIMER_TIME_MINUTE"]);
  14. 14 public static int SQL_TIME_MINUTE = Convert.ToInt32(ConfigurationManager.AppSettings["SQL_TIME_MINUTE"]);
  15. 15 public static int SQLTRAN_ERROR_NUMBER = Convert.ToInt32(ConfigurationManager.AppSettings["SQLTRAN_ERROR_NUMBER"]);
  16. 16
  17. 17 public static string LOG_PATH = ConfigurationManager.AppSettings["LOG_PATH"].ToString();
  18. 18 public static string WEIXIN_PUBLIC_URL = ConfigurationManager.AppSettings["WEIXIN_PUBLIC_URL"].ToString();
  19. 19 public static bool isgoing = true;
  20. 20 Dictionary<int, string> dic = new Dictionary<int, string>();
  21. 21 List<string> sqlList = new List<string>();
  22. 22 Dictionary<DateTime, int> dic_timer_run_error = new Dictionary<DateTime, int>();
  23. 23 #endregion
  24. 24 public SecKillRemindService()
  25. 25 {
  26. 26 InitializeComponent();
  27. 27 _Interval = 1000 * 60 * TIMER_TIME_MINUTE;//每隔?分钟执行
  28. 28 }
  29. 29 #region 事件方法
  30. 30 protected override void OnStart(string[] args)
  31. 31 {
  32. 32 // TODO: 在此处添加代码以启动服务。
  33. 33 _timer = new System.Timers.Timer(_Interval);
  34. 34 _timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
  35. 35 _timer.AutoReset = true;
  36. 36 _timer.Enabled = true;
  37. 37
  38. 38 }
  39. 39
  40. 40 protected override void OnStop()
  41. 41 {
  42. 42 // TODO: 在此处添加代码以执行停止服务所需的关闭操作。
  43. 43 CloseFile();
  44. 44 }
  45. 45 #endregion
  46. 46
  47. 47 #region 公用方法
  48. 48 private void OpenFile()
  49. 49 {
  50. 50 var path = LOG_PATH;
  51. 51 var fname = string.Format("\\{0}{1}{2}.txt", DateTime.Now.Year.ToString(), DateTime.Now.Month.ToString("D2"), DateTime.Now.Day.ToString("D2"));
  52. 52 if (!Directory.Exists(path))
  53. 53 {
  54. 54 Directory.CreateDirectory(path);
  55. 55 }
  56. 56 fs = new FileStream(path + fname, FileMode.Append);
  57. 57 sw = new StreamWriter(fs, Encoding.Default);
  58. 58 }
  59. 59 private void CloseFile()
  60. 60 {
  61. 61 sw.Close();
  62. 62 fs.Close();
  63. 63 }
  64. 64
  65. 65 #endregion
  66. 66
  67. 67 #region 自定义方法
  68. 68 BLL.SecKillRemind remind = new BLL.SecKillRemind();
  69. 69
  70. 70 /// <summary>
  71. 71 ///
  72. 72 /// </summary>
  73. 73 /// <param name="sender"></param>
  74. 74 /// <param name="e"></param>
  75. 75 private void Timer_Elapsed(object sender, ElapsedEventArgs e)
  76. 76 {
  77. 77 OpenFile();
  78. 78 sw.Write("-----------------开始检查----------------【" + DateTime.Now.ToString() + "】-------------开始检查--------------------\t\r\n");
  79. 79 CloseFile();
  80. 80 DateTime dt = DateTime.Now;
  81. 81 if (isgoing)
  82. 82 {
  83. 83 try
  84. 84 {
  85. 85 UserCheckOperation();
  86. 86 }
  87. 87 catch (Exception ex)
  88. 88 {
  89. 89 if (dic_timer_run_error[new DateTime().Date] < 100)
  90. 90 {
  91. 91 OpenFile();
  92. 92 sw.Write("-----------------检查出错----------------【" + DateTime.Now.ToString() + "" + ex.Message + "----------------结束出错-----------------\t\r\n");
  93. 93 CloseFile();
  94. 94 isgoing = true;
  95. 95 }
  96. 96 else
  97. 97 if (new Random(1000).Next() % 5 == 0)
  98. 98 {
  99. 99 isgoing = false;
  100. 100 dic_timer_run_error = new Dictionary<DateTime, int>();
  101. 101 }
  102. 102
  103. 103 dic_timer_run_error[new DateTime().Date] = dic_timer_run_error[new DateTime().Date] + 1;
  104. 104 }
  105. 105 }
  106. 106 }
  107. 107
  108. 108 public bool OperationByDictionary()
  109. 109 {
  110. 110 return true;
  111. 111 }
  112. 112
  113. 113 public void UserCheckOperation()
  114. 114 {
  115. 115 OpenFile();
  116. 116 int actId = 0; string actDateTime = DateTime.Now.ToString(); DateTime DateTimeNow = DateTime.Now;
  117. 117 List<Model.SecKillRemind> modellist = remind.GetModelList(10000, " Status<2 and ABS(datediff(MINUTE, GETDATE(), RemindDate1))<=" + SQL_TIME_MINUTE + " or ABS(datediff(MINUTE, GETDATE(), RemindDate2 ))<=" + SQL_TIME_MINUTE + " and Status<2 ", " AddDate ");
  118. 118 if (modellist != null ? modellist.Count > 0 ? true : false : false)
  119. 119 {
  120. 120 foreach (var item in modellist)
  121. 121 {
  122. 122 actId = item.SKP_Id == actId ? actId : (int)item.SKP_Id;
  123. 123
  124. 124 if (item.Status == 0)//checkDateTime((DateTime)item.RemindDate1, DateTimeNow) < SQL_TIME_MINUTE && item.Status == 0)
  125. 125 {
  126. 126 string result = MessageTemplte(item, item.RemindDate1.ToString());
  127. 127 dic[item.Id] = item.OpenId;
  128. 128 InserSql(sqlList, item, 1);
  129. 129 sw.Write("推送:【" + item.OpenId + "】成功" + DateTime.Now.ToString() + "" + result + " \t\r\n");
  130. 130 }
  131. 131 else if (item.Status == 1)//checkDateTime((DateTime)item.RemindDate2, DateTimeNow) < SQL_TIME_MINUTE && item.Status == 1)
  132. 132 {
  133. 133 string result = MessageTemplte(item, item.RemindDate2.ToString());
  134. 134 dic[item.Id] = item.OpenId;
  135. 135 InserSql(sqlList, item, 2);
  136. 136 sw.Write("推送:【" + item.OpenId + "】成功" + DateTime.Now.ToString() + "" + result + " \t\r\n");
  137. 137 }
  138. 138 }
  139. 139 }
  140. 140 else
  141. 141 {
  142. 142 sw.Write("-----------------暂无秒杀提醒数据-" + DateTime.Now.ToString() + "-----------------\t\r\n");
  143. 143 }
  144. 144 #region 操作数据库
  145. 145 if (new Random(100).Next() % 5 == 0)
  146. 146 {
  147. 147 bool tran = true; int tranCount = 0;
  148. 148 while (tran && tranCount < SQLTRAN_ERROR_NUMBER)
  149. 149 {
  150. 150 try
  151. 151 {
  152. 152 int c = DbHelperSQL.ExecuteSqlTran(sqlList);
  153. 153 if (c > 0)
  154. 154 {
  155. 155 tran = false;
  156. 156 tranCount += SQLTRAN_ERROR_NUMBER;
  157. 157 }
  158. 158 else
  159. 159 {
  160. 160 tranCount++;
  161. 161 }
  162. 162 }
  163. 163 catch (Exception)
  164. 164 {
  165. 165 tranCount++;
  166. 166 throw;
  167. 167 }
  168. 168 }
  169. 169 dic = tranCount >= SQLTRAN_ERROR_NUMBER ? new Dictionary<int, string>() : dic;
  170. 170 }
  171. 171 #endregion
  172. 172 isgoing = dic.Count <= 0 ? true : false;
  173. 173 sw.Write("-----------------结束检查----------------【" + DateTime.Now.ToString() + "】----------------结束检查-----------------\t\r\n");
  174. 174 CloseFile();
  175. 175 }
  176. 176
  177. 177 private static StringBuilder InserSql(List<string> sqlList, Model.SecKillRemind item, int st)
  178. 178 {
  179. 179 StringBuilder strSql = new StringBuilder();
  180. 180 strSql.Append(" update SecKillRemind set Status=" + st + " where Id=" + item.Id + " ");
  181. 181 sqlList.Add(strSql.ToString());
  182. 182 return strSql;
  183. 183 }
  184. 184
  185. 185 private static string MessageTemplte(Model.SecKillRemind item, string time)
  186. 186 {
  187. 187 WebClient webClient = new WebClient();
  188. 188 byte[] bt = webClient.DownloadData(WEIXIN_PUBLIC_URL + "/Service/SendTemplateMessage.ashx?type=seckill_remind&openid=" + item.OpenId + "&time=" + time + "");
  189. 189 string result = Encoding.UTF8.GetString(bt);
  190. 190 return result;
  191. 191 }
  192. 192
  193. 193 public static double checkDateTime(DateTime t1, DateTime now)
  194. 194 {
  195. 195 System.TimeSpan NowValue = new TimeSpan(t1.Ticks);
  196. 196 System.TimeSpan TimeValue = new TimeSpan(now.Ticks);
  197. 197 System.TimeSpan DateDiff = TimeSpan.Zero;
  198. 198 DateDiff = TimeValue.Subtract(NowValue).Duration();
  199. 199 return DateDiff.TotalMinutes;
  200. 200 }
  201. 201 #endregion
  202. 202 }
  203. 203 }
View Code

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号