当前位置:网站首页>Timing manager based on C #
Timing manager based on C #
2022-07-05 03:39:00 【Dotnet cross platform】
problem
We will encounter the following problems when using various systems :
12306 Buy train tickets on if 15 If the payment is not completed within minutes, the order will be automatically cancelled .
Reserved seats in the conference venue , If 10 If the payment is not completed within minutes, the reservation will be automatically cancelled .
After the specified time , I need to perform a task .
I have done many systems before , It is often a specific task that is performed on a regular basis . And the appeal problem involves the timing task of sliding window time .
such as : I am in the morning 10 spot 20 I booked a train ticket separately , I need to 15 Pay in minutes , Otherwise, the order will be canceled . Hundreds of people may book other train tickets at the same time , I need to be in everyone's 15 Check when the minute deadline expires , If it has not been paid, the order will be cancelled automatically .
programme
After we figure out the problem to be solved , Let's think about the plan . Experienced programmers will immediately think of the following solutions :
Use the delayed delivery function of message queue , Send a delay after each order is successfully added 15 Minute delay message . Order status processor 15 Message received in minutes , Check payment status , If not, cancel the order .
Redis There are similar functions , The principle is roughly the same .
But I don't want to use the function of message queue , Because delayed message delivery is a technical implementation , I hope to use code to reflect this business implementation , So use pure code to deal with him .( I'm not trying to reinvent the wheel , Because this is a business requirement , There will be a need for change and expansion , So I decided to try to increase my experience )
Algorithm ideas :
Our demand timing is 15 Within minutes, , Assume no more than 1 Hours or days .( If exceeded 1 Hour , This design can be extended , This article will not be discussed for the time being )
We can consider dividing an hour into 3600 second , Every second represents a location to store all expired orders , When placing an order, according to the current time add 15 Minute intervals , We can get it 15 Minutes later , Add this order to the corresponding location .
Data structure selection :
We choose C# The latest concurrent dictionary provided in is used as the basic data structure ,Key The value is 3600 The value of each second in seconds , The content is a queue used to store all orders at that point in time .
public ConcurrentDictionary<int, ConcurrentQueue<IJob>> jobs = new ConcurrentDictionary<int, ConcurrentQueue<IJob>>();
We have thought about the data structure , In fact, most of the functions are completed , The design of the code is basically settled .
Code implementation ( I like experimenting with console applications )
Set up a timing manager
public class TimerManager { // The concurrent dictionary stores the tasks that need to be checked ( Here can be the order check task , Each task can contain an order Id) public ConcurrentDictionary<int, ConcurrentQueue<IJob>> jobs = new ConcurrentDictionary<int, ConcurrentQueue<IJob>>(); private Timer timer; public TimerManager() { // Every interval 1 Once per second . Synchronize with the current time . timer = new Timer(ProcessJobs, null, 0, 1000); } }
Add a task to the dictionary
/// <summary> /// Add a task to the time dictionary /// </summary> /// <param name="timeKey"> Calculated according to the delay time key value </param> /// <param name="duetime"> Millisecond unit </param> /// <exception cref="NotImplementedException"></exception> public void AddJob(IJob job, TimeSpan duetime) { var key = GetKey(duetime); ConcurrentQueue<IJob> queue = new ConcurrentQueue<IJob>(); queue.Enqueue(job); jobs.AddOrUpdate(key, queue, (key, jobs) => { jobs.Enqueue(job); return jobs; }); }
Calculate according to time Key Methods
/// <summary> /// Generate the current key value according to the delay time /// </summary> /// <param name="duetime"></param> /// <returns></returns> private int GetKey(TimeSpan duetime) { var currentDateTime = DateTime.Now; // Due time var targetDateTime = currentDateTime.Add(duetime); // Don't forget to convert minutes into seconds , Then add it to the delay time to get Key var key = targetDateTime.Minute * 60 + targetDateTime.Second; return key; }
Add tasks to the dictionary
/// <summary> /// Add a task to the time dictionary /// </summary> /// <param name="job"> Tasks to be performed </param> /// <param name="duetime"> How many intervals do you check </param> public void AddJob(IJob job, TimeSpan duetime) { var key = GetKey(duetime); ConcurrentQueue<IJob> queue = new ConcurrentQueue<IJob>(); queue.Enqueue(job); // This is the method of concurrent dictionary , This is when Key If it doesn't exist, add a new value , When Key Existence exists in Key Add a new task to the queue of jobs.AddOrUpdate(key, queue, (key, jobs) => { jobs.Enqueue(job); return jobs; }); }
The method of processing tasks when the timer executes every second , Cycle to get tasks from the queue until all tasks are processed .
private async void ProcessJobs(object state) { // Calculate according to the current time Key value var key = DateTime.Now.Minute * 60 + DateTime.Now.Second; Console.WriteLine(key); // lookup Key Value the corresponding task queue and process . bool keyExists = jobs.TryGetValue(key, out var jobQueue); if (keyExists) { IJob job; while(jobQueue.TryDequeue(out job)) { await job.Run(); } } }
Design in code IJob and Job An implementation of , For ease of understanding , This job Not doing much . If you need to expand to check the order , You can record the order here Id, When creating a task, place an order ID Associated with the task , In this way, the timer can find the corresponding order when processing this task .
public interface IJob { Task Run(); } /// <summary> /// Represents a job /// </summary> public class Job : IJob { public Guid JobId { get; set; } public Job() { JobId = Guid.NewGuid(); } public async Task Run() { Console.WriteLine(" Job Id: " + JobId.ToString() + " is running."); await Task.Delay(2000); Console.WriteLine(" Job Id:" + JobId.ToString() + " have completed."); } }
The main program Programe Call the timing manager
using TimerTest; Console.WriteLine("Hello, World!"); TimerManager timerManager = new TimerManager(); Job job1 = new Job(); // Add a task 1 Execute in minutes timerManager.AddJob( job1, TimeSpan.FromMinutes(1)); // Adding another task in 2 Execute in minutes Job job2 = new Job(); timerManager.AddJob(job2, TimeSpan.FromMinutes(2)); Console.ReadLine();
Execution results
You can see in the results that , Mission 1 stay 1014 Is processed on the key value of ,1014 The time corresponding to the key value of is 16:54 second , That is, when I run this program 1 Minutes later .
Mission | Add the time | execution time |
---|---|---|
First mission ( timing 1 minute ) | 15:54 | 16:54 |
Second task ( timing 2 minute ) | 15:54 | 17:54 |
Mission 2 stay 1074 Is processed on the key value of ,1074 The corresponding time is 17:54 second perform . It can be seen from the above table that the program runs normally and the result is .
summary
This is a simple console program that verifies the implementation of the timing manager , We will 1 Hours are divided into 3600 second , Every second corresponds to one Key value , On this value, we store the tasks that need to be processed . When adding tasks , We also use the same algorithm to determine this Key value . When processing, divide by... According to the current time Key Value to process .
In this case , In the real world , We have 3600 individual Key Value can store all orders submitted by users every second , Time has not passed 1 I will deal with the corresponding task in seconds .
What can be improved later
We can add this class to ASP.NET MVC in , Use dependency injection for single instance lifecycle , Concurrent dictionaries and queues are thread safe , So you can use it safely .
We can expand Job Method , Add more information according to the business logic to facilitate processing . For example, processing orders ID, Or any other business ID.
The method of processing tasks can adopt multiple consumers to execute concurrently , Increase processing speed .
You can store task entities in the database , In order to deal with sudden downtime accidents, tasks can be rebuilt quickly .
Of course we can use Hangfire To easily realize this business .
var jobId = BackgroundJob.Schedule( () => Console.WriteLine("Delayed!"), TimeSpan.FromDays(7)); // Just change this to minutes
Finally, I wish .NET 20 Happy anniversary .
边栏推荐
- Multimedia query
- grandMA2 onPC 3.1.2.5的DMX参数摸索
- [Chongqing Guangdong education] 2777t green space planning reference questions of National Open University in autumn 2018
- Redis6-01nosql database
- Une question est de savoir si Flink SQL CDC peut définir le parallélisme. Si le parallélisme est supérieur à 1, il y aura un problème d'ordre?
- 有个疑问 flink sql cdc 的话可以设置并行度么, 并行度大于1会有顺序问题吧?
- Pat class a 1160 forever (class B 1104 forever)
- LeetCode 237. Delete nodes in the linked list
- Multi person online anonymous chat room / private chat room source code / support the creation of multiple chat rooms at the same time
- Three line by line explanations of the source code of anchor free series network yolox (a total of ten articles, which are guaranteed to be explained line by line. After reading it, you can change the
猜你喜欢
【无标题】
1. Five layer network model
Three line by line explanations of the source code of anchor free series network yolox (a total of ten articles, which are guaranteed to be explained line by line. After reading it, you can change the
[wp]bmzclub几道题的writeup
postman和postman interceptor的安装
Yyds dry goods inventory embedded matrix
Share the newly released web application development framework based on blazor Technology
SQL injection exercise -- sqli Labs
C file in keil cannot be compiled
[安洵杯 2019]不是文件上传
随机推荐
天干地支纪年法中为什么是60年一个轮回,而不是120年
【web源码-代码审计方法】审计技巧及审计工具
[vérification sur le Web - divulgation du code source] obtenir la méthode du code source et utiliser des outils
SQL performance optimization skills
Share the newly released web application development framework based on blazor Technology
Flume configuration 4 - customize mysqlsource
Single box check box
Yyds dry goods inventory embedded matrix
040. (2.9) relieved
[untitled]
Monitoring web performance with performance
51 independent key basic experiment
[安洵杯 2019]不是文件上传
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
程序员的视力怎么样? | 每日趣闻
Anchor free series network yolox source code line by line explanation four (a total of ten, ensure line by line explanation, after reading, you can change the network at will, not just as a participan
glibc strlen 实现方式分析
speed or tempo in classical music
Ubantu disk expansion (VMware)
Clickhouse同步mysql(基于物化引擎)