>백엔드 개발 >PHP 튜토리얼 >PHP 플래시 세일 기능 구현에 대한 아이디어 공유

PHP 플래시 세일 기능 구현에 대한 아이디어 공유

藏色散人
藏色散人앞으로
2020-09-29 11:43:597746검색

PHP 플래시 세일 기능 구현에 대한 아이디어 공유

추천: "PHP 동영상 튜토리얼"

1. 플래시 세일 사업이 어려운 이유

1) QQ나 웨이보 같은 IM 시스템, 여러분 (친구 목록, 그룹 목록, 개인 정보)

2) 모두가 팔로우하는 사람들의 데이터를 읽을 수 있습니다. 한 사람이 여러 사람의 데이터를 읽을 수 있습니다

3) 플래시 세일 시스템, 인벤토리는 하나뿐이고, 모두가 집중된 시간에 이 데이터를 읽고 쓰게 됩니다.

하나의 데이터를 여러 사람이 읽습니다.

예: Xiaomi 휴대폰은 매주 화요일에 플래시 세일을 합니다. 휴대폰은 10,000대에 불과하지만 순간 트래픽은 수백 또는 수천만에 이를 수 있습니다.

또 다른 예: 티켓 12306장, 티켓이 제한되어 있고, 인벤토리가 하나 있고, 순간적인 트래픽이 많고, 모두 동일한 인벤토리를 읽습니다.

읽기 및 쓰기 충돌, 잠금이 매우 심각하여 즉석 판매 업무가 어려운 곳입니다. 그렇다면 플래시 세일 사업의 구조를 어떻게 최적화할 수 있을까요?

2. 최적화 방향

두 가지 최적화 방향이 있습니다(오늘 이 두 ​​가지 사항에 대해 이야기하겠습니다).

(1)

시스템 업스트림에서 요청을 최대한 차단합니다 (잠금 충돌을 허용하지 않음) 데이터베이스에 떨어짐). 기존 플래시 세일 시스템이 실패하는 이유는 요청이 백엔드 데이터 레이어를 압도하고, 데이터 읽기-쓰기 잠금 충돌이 심각하고, 동시성이 높고 응답이 느리며, 트래픽이 많지만 거의 모든 요청이 타임아웃되기 때문입니다. 성공적인 주문에 대한 유효 트래픽은 매우 적습니다. 예를 들어 12306을 예로 들면 실제로 기차 티켓은 2,000장뿐입니다. 200만 명이 구매하러 오면 거의 아무도 성공적으로 구매할 수 없으며 요청 효율성은 0입니다.

(2)

캐시를 최대한 활용하여 순식간에 티켓을 구매하세요. 이는 대부분의 요청이 열차 번호 쿼리, 티켓 쿼리, 주문 및 결제 요청입니다. . 실제로 기차표는 2,000장밖에 안 되지만, 200만 명이 티켓을 사러 옵니다. 최대 2,000명이 성공적으로 주문을 하고, 그 외의 사람들은 모두 인벤토리를 조회합니다. 쓰기 비율은 0.1%에 불과하고 읽기 비율은 99.9%입니다. 캐싱 최적화에 매우 적합합니다. 자, "시스템 업스트림에서 요청을 최대한 가로채는 방법"과 "캐싱" 방법에 대해서는 나중에 이야기하고 자세한 내용은 이야기해 보도록 하겠습니다.

3. 일반적인 플래시 세일 아키텍처

일반적인 사이트 아키텍처는 기본적으로 이렇습니다. (절대 사기꾼 유형의 아키텍처 다이어그램을 그리지 마십시오.)

(1) 최상위 계층인 브라우저 측에서 실행됩니다. 일부 JS 코드

(2) 서버 측, 이 레이어는 백엔드 데이터에 액세스하고 HTML 페이지를 브라우저에 반환합니다

(3) 서비스 레이어(웹 서버), 업스트림에서 기본 데이터 세부 정보를 보호하고 제공합니다. 데이터 액세스

(4) 데이터 레이어, 최종 인벤토리가 여기에 저장되며 mysql이 일반적인 것입니다(물론 캐시됩니다)

이 그림은 간단하지만 높은 트래픽과 높은 동시성 플래시를 생생하게 보여줄 수 있습니다 판매 비즈니스 아키텍처 모두가 이 사진을 기억해야 합니다.

각 레벨을 최적화하는 방법은 나중에 자세히 분석하겠습니다.

4. 각 레벨의 최적화 세부 사항

첫 번째 레벨, 클라이언트 최적화 방법(브라우저 레이어, APP 레이어)

모두를 위한 질문입니다. 모두가 빨간 봉투를 얻기 위해 WeChat의 쉐이크를 플레이한 적이 있을 것입니다. 흔들 때마다 백엔드로 요청이 전송되나요? 티켓을 예매하기 위해 주문했던 장면을 보면, '조회' 버튼을 눌렀을 때 시스템이 멈춰버리고 진행바가 느리게 늘어나는 유저로서 무의식적으로 다시 '조회'를 눌렀죠? 계속 클릭하세요, 계속 클릭하세요, 클릭하세요, 클릭하세요. . . 유용합니까? 이유 없이 시스템 로드가 5회 증가했는데, 요청의 80%가 발생했습니다. 어떻게 해결하나요?

(a) 제품 수준에서 사용자가 "쿼리" 또는 "티켓 구매"를 클릭하면 버튼이 회색으로 표시되어

사용자가 반복적으로 요청을 제출할 수 없습니다.

(b) JS 수준에서 사용자는 다음과 같습니다. x초로 제한됨 요청 제출

APP 수준에서도 비슷한 작업을 수행할 수 있습니다. WeChat을 미친 듯이 흔들어도 실제로는 백엔드에 요청을 시작하는 데 x초밖에 걸리지 않습니다. 이것이 바로 "시스템에서 가능한 한 멀리 있는 업스트림 요청 차단"입니다. 업스트림이 많을수록 브라우저 계층과 APP 계층이 차단되므로 이 방법은 요청의 80% 이상만 차단할 수 있습니다. 일반 사용자 (그러나 사용자의 99%는 일반 사용자입니다.) 고급 프로그래머 그룹을 막을 방법은 없습니다. Firebug가 패킷을 캡처하자마자 JS는 프로그래머가 for 루프를 작성하고 요청의 이 부분을 호출하는 것을 막을 수 없습니다.

두 번째 계층, 서버 수준에서 차단 요청

어떻게 차단하나요? 프로그래머가 for 루프 호출을 작성하는 것을 방지하는 방법 중복 제거에 대한 근거가 있나요? IP? 쿠키 ID? ...이런 종류의 비즈니스에는 로그인이 필요합니다. uid를 사용하세요. 서버측 수준에서는 uid에 대한 요청 계산 및 중복 제거를 수행하며, 계산을 균일하게 저장할 필요도 없고 서버측 메모리에 직접 저장합니다(이 계산은 정확하지 않지만 가장 간단합니다). ). uid는 5초에 하나의 요청만 전달할 수 있으며 이는 for 루프 요청의 99%를 차단할 수 있습니다.

5초 안에 요청 하나만 통과되는데, 다른 요청은 어떻게 되나요? Cache, Page Cache, 동일한 uid, 액세스 빈도 제한, 페이지 캐싱을 수행하면 x초 내에 server에 도착하는 모든 요청은 동일한 페이지를 반환합니다. 기차 번호 등 동일한 항목에 대한 쿼리의 경우 페이지 캐싱이 수행되며 x초 내에 서버에 도착하는 요청은 모두 동일한 페이지를 반환합니다. 이러한 방식으로 흐름을 제한함으로써 사용자에게 좋은 사용자 경험을 보장할 수 있을 뿐만 아니라 (404가 반환되지 않음) 시스템의 견고성을 보장할 수도 있습니다(페이지 캐싱을 사용하여 서버에서 요청을 가로채기 ).

페이지 캐싱이 반드시 모든 서버가 일관된 페이지를 반환하도록 보장하는 것은 아닙니다. 각 사이트의 메모리에 직접 배치할 수도 있습니다. 장점은 간단하지만 단점은 http 요청이 서로 다른 서버에 속하고 반환되는 티켓 데이터가 다를 수 있다는 것입니다. 이것이 바로 서버의 요청 차단 및 캐시 최적화입니다.

좋아요, 이 방법은 for 루프를 작성하여 http 요청을 보내는 프로그래머를 막습니다. 일부 고급 프로그래머(해커)는 100,000개의 브로일러를 제어하고 100,000개의 uid를 손에 쥐고 동시에 요청을 보냅니다(실제 문제는 제쳐두고). - 이름 시스템, Xiaomi 휴대폰을 가져갈 때 실명 시스템이 필요하지 않습니다. 이제 서버가 uid 제한에 따라 중지할 수 없습니다.

세 번째 레이어는 가로채는 서비스 레이어입니다. (어쨌든 요청이 데이터베이스에 떨어지지 않도록 하세요.)

서비스 레이어를 가로채는 방법은 무엇인가요? 형제님, 저는 서비스 수준에 있습니다. Xiaomi에는 휴대폰이 10,000대 밖에 없다는 것을 분명히 알고 있습니다. 기차표가 2,000장 밖에 없다는 것을 데이터베이스에 요청하는 이유가 무엇입니까? 그렇죠, 요청큐!

쓰기 요청의 경우 요청 대기열을 생성하고 매번 제한된 수의 쓰기 요청만 데이터 계층으로 이동합니다(주문하고 해당 쓰기 비즈니스에 대한 비용 지불)

1w 휴대폰으로는 10,000개의 주문 요청만 이동 to the db

3k 기차표의 경우 3,000개의 주문 요청만 db로 전송됩니다

모두 성공하면 또 다른 배치가 배치됩니다. 재고가 충분하지 않으면 대기열의 모든 쓰기 요청이 "sold"로 반환됩니다. 밖으로".

읽기 요청을 최적화하는 방법은 무엇입니까? Memcached이든 Redis이든 캐시 저항은 단일 시스템이 초당 10W에 저항할 수 있다면 문제가 없습니다. 이러한 전류 제한을 사용하면 쓰기 요청과 읽기 캐시 오류 요청이 거의 데이터 계층에 침투하여 요청의 99.9%가 차단됩니다.

물론 비즈니스 규칙에도 몇 가지 최적화가 있습니다. 12306이 했던 일을 생각해보면, 시간별, 구간별 티켓 판매 예전에는 10시에 티켓을 판매했는데 지금은 8시, 8시 30분, 9시에 티켓을 판매하고... 30분마다 배치를 릴리스합니다. 트래픽을 균등하게 분산합니다.

둘째, 데이터 세분성 최적화: 티켓 구매하러 가면 남은 티켓 조회 업무가 58장, 아니면 26장 남았네요. 사실 저희는 티켓만 신경쓰고 티켓은 신경쓰지 않죠? ? 트래픽이 많은 경우 "티켓 있음" 및 "티켓 없음"의 대략적인 캐시를 만드세요.

셋째, 일부 비즈니스 로직의 비동기성: 주문 비즈니스와 결제 비즈니스의 분리 등. 이러한 최적화는 모두 비즈니스와 결합됩니다. 저는 이전에 "비즈니스와 분리된 모든 아키텍처 디자인은 로그"라는 관점을 공유했습니다.

자, 드디어 데이터베이스 계층

브라우저가 80%를 가로채고, 서버가 99.9%를 가로채서 페이지를 캐시했습니다. 서비스 계층도 쓰기 요청 대기열과 데이터 캐싱을 수행했는데, 이는 매번 데이터베이스 계층에 침투했습니다. 요청은 제어 가능합니다. 기본적으로 DB에 대한 부담은 없고, 한 대의 머신으로 처리할 수 있으며, 역시 재고가 한정되어 있고, 샤오미의 생산 능력도 한계가 있어 데이터베이스에 요청을 많이 하는 것은 의미가 없습니다.

모두 데이터베이스로 전송되고, 100만개 주문이 접수되었으며, 0개가 성공하고, 요청 효율이 0%입니다. 3,000개의 데이터를 얻었고 모두 성공했으며 요청 효율성은 100%였습니다.

5. 요약

위의 설명은 매우 명확해야 합니다. 플래시 세일 시스템에 대해서는 개인적인 경험에서 나온 두 가지 아키텍처 최적화 아이디어를 반복하겠습니다.

(1) 가로채기 시도 시스템의 업스트림 요청 (업스트림이 많을수록 좋음)

(2) 더 많이 읽고 더 적게 쓰는 캐시 (캐시는 읽기 압력에 저항함)

브라우저 및 앱: 속도 제한

서버: uid 기반 속도 제한, 페이지 캐싱

서비스 계층(웹 서버): 비즈니스 기반 쓰기 요청 대기열 제어 트래픽, 데이터 캐싱

데이터 계층: 여유로운 산책

그리고: 최적화 기반 비즈니스

6 , Q&A

질문 1. 귀하의 아키텍처에 따르면 가장 큰 압박을 받는 것은 실제로 서버입니다. 실제 유효 요청 수가 1,000만 개라고 가정하면 요청 연결 수를 제한할 가능성이 없습니다. 이 부분의 압력으로?

답변: 초당 동시성은 1kw가 아닐 수 있습니다. 1kw라고 가정하면 두 가지 해결책이 있습니다.

(1) 최악의 경우 기계를 추가하여 서비스 계층(웹 서버)을 확장할 수 있습니다.

(2) 머신이 충분하지 않으면 요청을 폐기하고 50%를 폐기합니다(50%는 직접 반환되고 나중에 다시 시도됩니다). 시스템을 보호하고 모든 사용자가 실패하지 않도록 하는 것이 원칙입니다.

질문 2. "100,000마리의 육계를 제어하고, 100,000개의 UID를 보유하고 동시에 요청을 보냅니다." 이 문제를 해결하는 방법은 무엇입니까?

답변: 위에서 언급한 것처럼 서비스 계층(웹 서버) 쓰기 요청 대기열 제어

질문 3: 액세스 빈도를 제한하는 캐시를 검색에도 사용할 수 있나요? 예를 들어, 사용자 A가 "휴대폰"을 검색하고 사용자 B가 "휴대폰"을 검색하는 경우 A의 검색으로 생성된 캐시된 페이지가 먼저 사용됩니까?

답변: 이 방법은 4kw 사용자 앱의 단기 푸시-푸시 작업 활동 및 페이지 캐싱과 같은 "동적" 작업 활동 페이지에서도 자주 사용됩니다.

질문 4: 대기열 처리가 실패하면 어떻게 해야 하나요? 육계가 줄을 서면 어떻게 해야 합니까?

답변: 처리가 실패하면 주문이 실패한 것으로 반환되며 사용자는 다시 시도할 수 있습니다. 대기열 비용이 매우 낮기 때문에 폭발하기 어려울 것입니다. 최악의 경우 여러 요청이 캐시된 후 후속 요청은 "티켓 없음"을 직접 반환합니다. (대기열에 이미 100만 개의 요청이 있고 모두 대기 중이므로 더 이상 요청을 수락할 필요가 없습니다.)

질문 5: 서버 필터링을 위해 uid 요청 개수를 각 사이트의 메모리에 별도로 저장하나요? 그렇다면 여러 서버 클러스터가 로드 밸런서를 통해 동일한 사용자의 응답을 다른 서버로 분산시키는 상황을 어떻게 처리해야 할까요? 아니면 로드 밸런싱 전에 서버에 필터링을 넣어야 할까요?

답변: 메모리에 배치할 수 있습니다. 이 경우 하나의 서버는 5초에 1개의 요청으로 제한되는 것 같지만(머신이 10개 있다고 가정) 실제로는 5초에 10개의 요청으로 제한됩니다.

1) 큰 제한 추가(가장 간단한 권장 솔루션)

2) nginx 레이어에서 7레이어 밸런싱을 수행하여 uid 요청이 가능한 한 동일한 시스템에 속하도록

질문 6: 서비스 레이어(웹 서버)가 필터링한다면 큐는 서비스 레이어(웹 서버)의 통합 큐인가요? 아니면 서비스를 제공하는 각 서버마다 대기열이 있나요? 통합 큐라면 각 서버에서 제출한 요청을 큐에 넣기 전에 잠금 제어를 수행해야 합니까?

답변: 대기열을 통합할 필요는 없습니다. 이 경우 각 서비스는 더 적은 수의 요청(총 투표 수/서비스 수)을 전달할 수 있습니다. 대기열을 통합하는 것은 또 다시 복잡해집니다.

질문 7: 플래시 세일 후 결제가 완료되고 결제 없이 자리표시자가 취소된 후 적시에 남은 재고를 관리하고 업데이트하는 방법은 무엇인가요?

답변: 데이터베이스에 미지급 상태가 있습니다. 예를 들어 시간이 45분을 초과하면 재고가 다시 복원됩니다("창고로 복귀"라고 함). 우리가 티켓을 구매하게 된 계기는 플래시 세일을 시작한 후 아마도 45분 후에 다시 시도하는 것입니다. 또 티켓이 생길 거예요~

질문 8: 서로 다른 사용자가 동일한 제품을 탐색하고 서로 다른 캐시 인스턴스에 표시되는 인벤토리가 완전히 다릅니다. 캐시 데이터를 일관되게 만드는 방법이나 더티 읽기를 허용하는 방법을 알려주실 수 있나요?

답변: 현재 아키텍처 설계에서는 요청이 다른 사이트에 속하며 데이터가 일관되지 않을 수 있습니다(페이지 캐시가 다름). 이 비즈니스 시나리오는 허용됩니다. 그러나 데이터베이스 수준의 실제 데이터에는 문제가 없습니다.

질문 9: 비즈니스 최적화에서 "3,000개 기차표, 3,000개 주문 요청만 db로 이동"을 고려하더라도 이러한 3,000개 주문이 혼잡을 유발하지 않나요?

답변: (1) 데이터베이스는 여전히 3k 쓰기 요청을 견딜 수 있습니다. (2) 데이터는 분할될 수 있습니다. (3) 3k가 이를 처리할 수 없으면 서비스 계층 (웹 서버) 이 동시 연결 수를 제어할 수 있습니다. 스트레스 테스트 상황에 따르면 3k는 단지 예시일 뿐입니다.

질문 10; 서버 또는 서비스 계층(웹 서버)에서 백그라운드 처리가 실패하는 경우 실패한 요청 일괄 재생을 고려해야 합니까? ? 아니면 그냥 버리나요?

답변: 쿼리가 실패하거나 주문이 실패하면 다시 재생하지 마세요. 아키텍처 설계 원칙 중 하나는 '빠른 실패'입니다.

질문 11. 12306 등 대형 시스템의 플래시 세일이 동시에 진행되고 있는데, 어떻게 전환할 수 있나요?

답변: 수직 분할

질문 12. 또 다른 질문이 떠오릅니다. 이 프로세스는 동기식인가요, 비동기식인가요? 동기화되면 응답 피드백이 느려집니다. 그러나 비동기식인 경우 응답 결과가 올바른 요청자에게 반환될 수 있는지 여부를 어떻게 제어할 수 있습니까?

답변: 사용자 수준은 확실히 동기식이며(사용자의 http 요청은 억제됨) 서비스 계층 (웹 서버) 은 동기식 또는 비동기식일 수 있습니다.

질문 13. 깜짝세일 단체 질문: 어느 단계에서 재고를 줄여야 할까요? 인벤토리 잠금을 주문하는 경우 다수의 악의적인 사용자가 비용을 지불하지 않고 인벤토리 잠금을 주문하면 어떻게 해야 합니까?

답변: 데이터베이스 수준의 쓰기 요청 수가 매우 적습니다. 다행히도 주문이 지불되지 않습니다. 앞서 언급한 대로 "위치로 돌아가기" 전에 시간이 경과할 때까지 기다리십시오.

팁: 주의할 점

1. 원래 사이트 배포에서 분리합니다. (플래시 세일 기능을 위한 서버와 쇼핑몰 서버는 동일한 서버에 배치되어서는 안 됩니다. 쇼핑몰 접속불가...)

2. 다중 모니터링, 모니터링에 주의, 지켜줄 사람 찾기

플래시 세일의 핵심 포인트:

1. 고가용성: 액티브-액티브

2. : 로드 밸런싱, 보안 필터링

디자인 아이디어:

1 정적 페이지: CDN(주요 제조업체의 기성품 사용), URL 숨기기, 페이지 압축, 캐싱 메커니즘

2 동적 페이지: 대기열, 비동기, 검증 서두르세요

기타 제안:

1. Baidu의 제안: opcode 캐시, CDN, 대규모 서버 인스턴스

2. Alibaba의 제안: 클라우드 모니터링, 클라우드 쉴드, ecs, oss, rds, cdn

cdn 아이디어 사용:

1. 정적 리소스(그림, js, css 등)를 사용합니다. ) cdn에 업로드

2. 단점: 하지만 업데이트할 때 cdn이 제때 업데이트되지 않으므로 push해야 합니다

현재를 인식합니다. 환경 및 형태:

1. 사용자: 매우 많은 수, 정상/나쁜 사람들 (cdn 가속도 근처의 CDN 노드에 액세스하기 때문에 일종의 전환입니다.)

2. 지역: 전국 (1 시간 지연) 또는 2초만으로는 부족합니다. 1초의 지연이 순식간에 끝날 수도 있고, 사용자가 근처 노드를 선택할 수 있도록 하려면 CDN이 필요하기 때문입니다.)

3 ,업무 프로세스: 프론트 데스크에서 제품 전시 및 등록. 백엔드 데이터 액세스 및 데이터 처리

다른 제품을 전환하고 홍보하기 위해 플래시 세일 전에 페이지를 추가하세요

제품 디스플레이 레이어 구조

페이지의 3가지 상태:

1. 제품 디스플레이: 카운트다운 페이지

2. 플래시 세일 진행 중: 클릭하여 플래시 세일 페이지로 이동

3. 플래시 세일 종료: 이벤트가 종료되었음을 알리는 메시지

새로운 아이디어: 타임라인 측면에서 문제를 생각해 보세요

가정 우리가 보는 것은 플래시 세일 진행 중, 앞으로 밀면 카운트다운, 뒤로 밀면 끝

아래 그림은 사용자 관점에서 문제를 보여줍니다.

코드:

정적 리소스 , 배포를 위해 oss에 저장됨

먼저 카운트다운 페이지를 삭제하고 즉시 플래시 세일 페이지에 복사하세요

그런 다음 coretab을 사용하여 이 스크립트를 정기적으로 실행하세요

요약:

카운트다운부터 러시 세일까지: Linux 예약 작업 및 쉘 스크립트를 사용하여 수행됩니다

급매는 끝났습니다. PHP를 사용하여 수행하고 테이블이 없어지면 종료됩니다

사용자 등록 계층 구조

코드 :

$.cookie encapsulation

데이터 액세스 레이어

코드:

레이어 2에서 레이어까지 계산하는 방법 3? ?

계층 2에서 계층 3으로 데이터를 전송하고 네트워크 전송 DNS 확인 및 기타 요인으로 인해 발생하는 총 지연 시간은 얼마나 됩니까? 이를 통해 구성해야 하는 서버 수를 평가할 수 있습니다

두 문장으로 요약:

1. 키포인트가 통과되지 않으면 바로 이전 레이어(사용자 등록 레이어)로 돌아갑니다.

2. 키포인트가 통과되면 다른 레이어에 통보됩니다

효과: 암호화 및 복호화와 유사합니다. Microsoft 일련 번호

queue : redis를 사용하여 주문한 컬렉션

상한: 기술 플래그 비트

데이터 처리 계층

 

 

위 내용은 PHP 플래시 세일 기능 구현에 대한 아이디어 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제