当前位置: 移动技术网 > IT编程>开发语言>.net > 推送算法小结

推送算法小结

2018年10月22日  | 移动技术网IT编程  | 我要评论

义马市,移通学院教务网,会呼吸的痛吉他谱

秒杀提醒执行算法分析

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

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

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网