I saw someone analyzing the backend logic of 12306 before. . Booking and canceling train tickets is different from ordinary shopping.
One problem is that train tickets can be sold at different stations. For example, a train ticket from Beijing to Shanghai can have many stops along the way, such as Beijing-Jinan, Jinan-Nanjing...and so on. How to design a data model to access these tickets is a problem. Instead of a simple quantity -1.
I saw a good idea among them: use a binary string to represent a train ticket. For example, there are 10 stations in total from Beijing to Shanghai, then the initial state of a full-distance ticket is: '1111111111';
Sell If you buy a full-journey ticket, the ticket becomes '0000000000';
If you sell a half-journey ticket, such as Beijing-Jinan three stations (first stop - third stop), the ticket will become '0011111111';
If you sell another half-distance ticket, such as Xuzhou-Nanjing (stop 6-9), the previous ticket will become: '0011100011';
The logic of canceling a ticket is very simple. If I want to refund a ticket (Xuzhou-Nanjing), I will find the first ticket from the ticket pool that cannot be purchased
(Xuzhou-Nanjing) and change it. OK (the reverse of buying a ticket). For example, if you find the above ticket '0011100011',
after the refund, the ticket becomes (0011111111);
The basic logic is as above. 12306 needs to ensure multiple entries and data consistency at the same time, which requires very efficient logic to handle ticket checking.
The business of buying and refunding tickets is said to have 200,000 requests per second at the peak. Save the ticket data structure in memory. rather than a database.
Small and efficient data structures become important.
function Server(){
var self = this;
self.ticketsPool = [];
self._init= function(number){
if(typeof(number) != 'number')
throw ('type error');
for(i=0;i
}
};
//Determine whether a ticket can be purchased through AND or OR operations.
//For example: Order o is Beijing-Jinan (001111111), and a certain ticket is (0000000011) (Beijing-Nanjing has been sold), then return false
//For example: Order o is Beijing-Jinan ( 001111111), a certain ticket is (1111100011) (sold Xuzhou-Nanjing), then return true
self.canBuy = function(o,t){
var _o = ''
for(j =0; j
}
var r1 = (parseInt(t.tic,2) | parseInt(o,2)) & parseInt(_o,2);
var r2 = parseInt(_o,2);
return r1 == r2;
};
//Sell a ticket
self.pop1Ticket = function(o){
for(i=0;i < self.ticketsPool.length;i ){
if(self. canBuy(o,self.ticketsPool[i])){
self.buy(self.ticketsPool[i],o);
return i;
}
};
return - 1;
};
//Implementation of selling tickets, changing the binary string, such as '111111111'->'001111111';
self.buy = function(t,o){
t.tic = (parseInt (t.tic,2) & parseInt(o,2)).toString(2);
//alert(t.tic);
};
//Query remaining tickets
self.remainTics = function(o){
var count=0;
for(i=0;i < self.ticketsPool.length;i ){
count = self.canBuy(o,self.ticketsPool[i])?1:0;
};
return count;
}
//Refund, or operation
self.refund = function(o){
for(i=0;i < self.ticketsPool.length;i ){
if(!self. canBuy(o,self.ticketsPool[i])){
var _o = ''
for(j=0; j
}
self.ticketsPool[i].tic = (parseInt(self.ticketsPool[i].tic,2) | parseInt(_o,2)).toString(2 );
return i;
}
};
return -1;
}
}
//Data model: ticket
function Ticket(){
var self = this;
//The initial ticket is a full ticket
self.tic = '1111111111';
}
//Data model: Order
function Order(from, to){
var self = this;
var s = '';
for(i=0;i<10; i ){
s = (i>=from && i
return s;
}
//12306 Backend
Server = new Server();
//Initial state, the ticket pool has 400 full tickets
Server._init(400);