秒杀提醒执行算法分析

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

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

View Code

 

版权声明:本文为HonkerXin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/HonkerXin/p/9815697.html