전에 12306의 백엔드 로직을 분석하는 분을 본 적이 있습니다. . 기차표 예약 및 취소는 일반 쇼핑과 다릅니다.
한 가지 문제는 기차표를 여러 역에서 판매할 수 있다는 것입니다. 예를 들어, 베이징에서 상하이까지 가는 기차표에는 베이징-제남, 제남-난징 등 여러 정거장이 있을 수 있습니다. 이러한 티켓에 액세스하기 위한 데이터 모델을 설계하는 방법이 문제입니다. 단순한 수량 대신 -1.
그 중에서 좋은 아이디어를 봤습니다. 기차표를 나타내기 위해 바이너리 문자열을 사용하는 것입니다. 예를 들어 베이징에서 상하이까지 총 10개의 역이 있다면 전체 거리 티켓의 초기 상태는 '1111111111'입니다. ;
판매 전체 여정 티켓을 구매하면 티켓은 '0000000000'이 됩니다.
베이징-지난 3역(첫 번째 정류장~세 번째 정류장) 등 반 여정 티켓을 판매하는 경우,
쉬저우-난징(6-9번 정류장) 등 다른 반거리 티켓을 판매하는 경우 이전 티켓은 '0011100011'이 됩니다.
티켓 취소 논리는 매우 간단합니다. 티켓(쉬저우-난징)을 환불하려면
(쉬저우-난징) 티켓 풀에서 첫 번째 티켓을 찾아 변경하면 됩니다. (티켓 구매의 역순) 예를 들어 위의 티켓 '0011100011'을 찾으면
환불 후 티켓은
기본 로직은 위와 같습니다. 12306은 다중 입력과 데이터 일관성을 동시에 보장해야 하는데, 이는 티켓 확인을 처리하기 위해 매우 효율적인 로직이 필요합니다.
티켓 구매 및 환불 업무는 20만 건의 요청이 있다고 합니다. 최고점에서 초당. 티켓 데이터 구조를 메모리에 저장합니다. 데이터베이스보다는.
작고 효율적인 데이터 구조가 중요해졌습니다.
function Server(){
var self = this;
self.ticketsPool = [];
self._init= function(number){
if(typeof(number) != 'number')
throw('type error');
for(i=0;i
}
};
//AND 또는 OR 연산을 통해 티켓을 구매할 수 있는지 확인합니다.
//예: 주문 o는 베이징-지난(001111111)이고 특정 티켓은 (0000000011)(베이징-난징이 매진됨)인 경우 false를 반환합니다.
//예: 주문 o는 베이징입니다. -Jinan(001111111), 특정 티켓은 (1111100011)(Xuzhou-Nanjing에서 판매), true를 반환
self.canBuy = function(o,t){
var _o = ''
for( j =0; j
}
var r1 = (parseInt(t.tic,2 ) | 파싱(o,2)) & 파싱(_o,2);
var r2 = 파싱(_o,2);
return r1 == r2;
};
//티켓 판매
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;
};
//티켓 판매 구현, '111111111'->'001111111'과 같은 바이너리 문자열 변경;
self.buy = function(t,o){
t.tic = (parseInt (t.tic,2) & parsInt(o,2)).toString(2);
//alert(t.tic);
};
//남은 티켓 쿼리
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;
}
//환불 또는 연산
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;
}
};
반환 -1;
}
}
//데이터 모델: ticket
function Ticket(){
var self = this;
//초기 티켓은 전체 티켓입니다
self.tic = '1111111111';
}
//데이터 모델: Order
function Order(from, to){
var self = this;
var s = '';
for(i=0;i<10; i ){
s = (i>=from && i
return s;
}
//12306 백엔드
Server = new Server();
//초기 상태, 티켓 풀에 400개의 전체 티켓이 있습니다
Server._init(400);