나는 누군가가 전에 12306 배경의 논리를 분석하는 것을 보았다. . 기차 티켓의 예약 및 구독 거부는 일반 쇼핑과 다릅니다.
한 가지 문제는 기차 티켓이 다른 스테이션에서 판매 할 수 있다는 것입니다. 예를 들어, 베이징에서 상하이까지의 기차 티켓을 따라 베이징-제난, 진안 난징 등과 같은 많은 방송국이 있습니다. 이러한 티켓에 액세스하기 위해 데이터 모델을 설계하는 방법은 문제입니다. 간단한 수량 대신 +-1.
한 가지 아이디어는 매우 좋습니다. 이진 문자열을 사용하여 기차 티켓을 나타냅니다. 예를 들어, 베이징에서 상하이까지 10 개의 스테이션이 있으며 전체 티켓의 초기 상태는 다음과 같이 표현됩니다. '111111111';
전체 티켓이 판매되면 티켓은 '000000000'이됩니다.
베이징-제난 3 스테이션 (첫 번째 스테이션 세 번째 스테이션)과 같은 반쯤 티켓을 판매하는 경우 티켓은 '00111111111'이됩니다.
Xuzhou-Nanjing (6 스토프 9 스톱)과 같은 또 다른 반쯤 티켓을 판매하면 이전 티켓이 다음과 같습니다. '0011100011';
구독되지 않은 티켓의 논리는 매우 간단합니다. 티켓 (Xuzhou-Nanjing)을 환불하려면 티켓 수영장에서 첫 번째 티켓을 찾아 구매할 수 없습니다.
(Xuzhou-Nanjing) 티켓을 변경하면 괜찮습니다 (티켓 구매의 반대 방향). 예를 들어, 위의 티켓 '0011100011'을 찾았습니다.
티켓을 환불 한 후 티켓은 (0011111111)가됩니다.
기본 논리는 위와 같습니다. 12306은 여러 입구를 보장해야하며 동시에 데이터의 일관성은 티켓 수표를 처리하기 위해 매우 효율적인 논리가 필요합니다.
티켓 구매에 대한 초당 200,000 개의 요청이 있으며 피크 타임에 티켓 환불이있을 것이라고합니다. 티켓의 데이터 구조를 메모리에 저장하십시오. 데이터베이스가 아닙니다.
작고 효율적인 데이터 접합이 중요해집니다.
코드 사본은 다음과 같습니다.
if (jQuery) {} else {
//document.write
}
기능 서버 () {
var self = 이것;
self.ticketspool = [];
self._init = function (number) {
if (typeof (number)! = 'number')
던지기 ( '유형 오류');
for (i = 0; i <번호; i ++) {
self.ticketspool.push (new ticket ());
}
};
// 티켓을 구입할 수 있는지 여부와 및 작업을 통해 달성 할 수 있습니다.
// 예 : Order O는 Beijing-Jinan (001111111)이고 특정 티켓은 (0000000011) (Beijing-Nanjing 판매)이고 False를 반환합니다.
// 예 : Order O는 Beijing-Jinan (001111111)이고 특정 티켓은 (1111100011) (Xuzhou-Nanjing에서 판매)입니다.
self.canbuy = function (o, t) {
var _o = ''
for (j = 0; j <O.length; j ++) {
_o += o [j] == '0'? 1 : 0;
}
var r1 = (parseint (t.tic, 2) | parseint (o, 2)) & parseint (_o, 2);
var r2 = parseint (_o, 2);
반환 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);
반환 i;
}
};
반품 -1;
};
// 티켓 판매 구현, '11111111'-> '00111111'과 같은 이진 문자열 변경;
self.buy = function (t, o) {
t.tic = (parseint (t.tic, 2) & parseint (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;
};
반환 수;
}
// 환불 또는 작동
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 <O.length; j ++) {
_o += o [j] == '0'? 1 : 0;
}
self.ticketspool [i] .tic = (parseint (self.ticketspool [i] .tic, 2) | parseint (_o, 2)). Tostring (2);
반환 i;
}
};
반품 -1;
}
}
// 데이터 모델 : 티켓
함수 티켓 () {
var self = 이것;
// 티켓은 티켓의 시작입니다
self.tic = '1111111111';
}
// 데이터 모델 : 순서
함수 순서 (부터) {
var self = 이것;
var s = '';
for (i = 0; i <10; i ++) {
s += (i> = from && i <to)? 0 : 1;
}
반환 s;
}
// 12306 무대 뒤
Server = 새 서버 ();
// 초기 상태, 티켓 풀에는 400 개의 전체 티켓이 있습니다
Server._init (400);