欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

推送算法小结

程序员文章站 2022-08-09 17:38:53
秒杀提醒执行算法分析 秒杀提醒要求:活动开始 前一个小时 提醒一次;活动开始 前五分钟再 提醒一次;提醒记录表存已存有两次提醒时间; 状态为 0 、1 、2 分别表示 未提醒 、提醒一次 、提醒两次 。查询只查询0 、1 推送方式采用 微信模板消息 提醒用户,程序编程采用 windows服务 形式进 ......

秒杀提醒执行算法分析

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

  • 状态为 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