当前位置:网站首页>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 .
边栏推荐
- Kubernetes - Multi cluster management
- De debugging (set the main thread as hidden debugging to destroy the debugging Channel & debugger detection)
- About authentication services (front and back, login, registration and exit, permission management)
- [2022 repair version] community scanning code into group activity code to drain the complete operation source code / connect the contract free payment interface / promote the normal binding of subordi
- Kuboard
- 2. Common request methods
- postman和postman interceptor的安装
- Port, domain name, protocol.
- Anti debugging (basic principles of debugger Design & NT NP and other anti debugging principles)
- Nmap使用手册学习记录
猜你喜欢
LeetCode146. LRU cache
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
Huawei MPLS experiment
Basic knowledge of tuples
【无标题】
Pat class a 1160 forever (class B 1104 forever)
Class inheritance in C #
Easy processing of ten-year futures and stock market data -- Application of tdengine in Tongxinyuan fund
【web源码-代码审计方法】审计技巧及审计工具
【web审计-源码泄露】获取源码方法,利用工具
随机推荐
Subversive cognition: what does SRE do?
De debugging (set the main thread as hidden debugging to destroy the debugging Channel & debugger detection)
Basic authorization command for Curl
Binary heap implementation (priority queue implementation)
New interesting test applet source code_ Test available
[groovy] string (string type variable definition | character type variable definition)
汇编-入门
Dart series: collection of best practices
El select, El option drop-down selection box
Devtools的簡單使用
Flume configuration 4 - customize mysqlsource
Use UDP to send a JPEG image, and UPD will convert it into the mat format of OpenCV after receiving it
Utilisation simple de devtools
grandMA2 onPC 3.1.2.5的DMX参数摸索
DECLARE_ WAIT_ QUEUE_ HEAD、wake_ up_ Interruptible macro analysis
Hot knowledge of multithreading (I): introduction to ThreadLocal and underlying principles
Easy processing of ten-year futures and stock market data -- Application of tdengine in Tongxinyuan fund
Basic knowledge of tuples
英语必备词汇3400
【无标题】