Redis 인벤토리 과매도 문제 해결

coldplay.xixi
풀어 주다: 2021-03-18 11:20:02
앞으로
2798명이 탐색했습니다.

Redis 인벤토리 과매도 문제 해결

제품과 주문 서비스 사이에 MQ를 사용하세요

제품 서비스의 재고가 변경되면 MQ를 통해 주문 서비스에 재고 변경 사항이 통보됩니다.

원래 동기화 프로세스

  1. 상품 정보 조회(상품 서비스 호출)
  2. 총액 계산(주문 내역 생성)
  3. 상품 서비스에서 재고 차감(상품 서비스 호출)
  4. 입고 주문(주문 생성)
// 原始的MySQL同步流程// 判断此代金券是否加入抢购SeckillVouchers seckillVouchers = seckillVouchersMapper.selectVoucher(voucherId);AssertUtil.isTrue(seckillVouchers == null, "该代金券并未有抢购活动");// 判断是否有效AssertUtil.isTrue(seckillVouchers.getIsValid() == 0, "该活动已结束");// 插入数据库seckillVouchersMapper.save(seckillVouchers);
로그인 후 복사

추천(무료): redis

주문 발생 시 직접 재고를 차감하는 가장 독창적인 재고 차감 방식이지만

문제

  • 가 있습니다. 많은 주문이 발생할 수 있습니다. 결제 없이 제품 재고를 차감하려면 일정 기간 결제되지 않은 주문의 재고를 해제하고 주문을 취소
  • 즉시 재고를 차감하고 차액을 발행하는 백그라운드 스크립트가 필요합니다

1. 3단계 상품 서비스, 상품 서비스를 위한 운영 DB, 2단계 및 4단계 주문 서비스, 운영 주문 서비스를 위한 DB.

다른 서비스의 DB에 대한 접근을 피하세요. 원칙적으로 동일한 서비스는 자체 서비스의 DB만 운영할 수 있습니다.

MQ 비동기화

먼저 4단계만 비동기화하는 것을 고려해 보세요.

Analytic

2,4는 모두 DB에서 작업되며, 4단계는 더 이상 기다리지 않으며, 1, 2, 3단계가 성공하면 즉시 사용자에게 피드백이 제공됩니다.

이후 메시지 알림 서비스를 통해 비동기식으로 주문이 이루어집니다. 4단계에서 비동기식 주문이 실패하면 작업을 다시 시도하고 MQ 메시지도 추적할 수 있습니다.

주문이 생성된 후 대기열 상태가 되며 서비스는 Order Created 이벤트를 메시지 대기열에 게시합니다. Order Created 到消息队列中。
即订单服务向外界发送消息:我创建了一个订单,由MQ 转发给订阅该消息的服务。

如果商品服务收到创建订单消息之后执行扣库存操作。注意,这里可能因为某些不可抗因素导致扣库存失败,无论成功与否,商品服务都会发送一个扣库存消息到 MQ,消息内容即扣库存的结果。
订单服务会订阅扣库存的结果,接收到该消息后:

  • 如果扣库存成功,将订单的状态改为已确认,即下单成功
  • 如果扣库存失败,将订单的状态改为已取消,即下单失败

欲实现上述模型要求,需可靠的消息投递。服务发出的消息,一定会被MQ收到。

  • 用户体验的变化
    前端配合排队中等界面。

商品/订单服务都变成异步化,适合秒杀类场景,当流量不大时,并不太适合。

异步设计

  1. 库存在Redis中保存
  2. 收到请求Redis判断是否库存充足 ,减掉Redis中库存
  3. 订单服务创建订单写入数据库,并发送消息

当订单支付成功后,会有一个出库过程,既然有这个过程,就有可能出库失败。
库存有两部分:

  • 缓存redis层
  • 数据库mysql层
  1. 当客服新增5个库存,则缓存redis和数据库mysql层都需增加5个库存,使用分布式事务的最终一致性来满足:库存要么全加,要么全不加。
  2. 当订单生成时,需要扣除库存,先扣redis库存,如果扣除成功,则生成订单进行支付,这个过程不扣除mysql库存
  3. 当redis库存扣完,该产品就无法下单了,下单就会失败,就把外层的给挡住了。
  4. 在第2步扣除redis库存成功后,生成订单,进行支付,支付成功,返回我的订单中心, 会发现有一个出库过程。
  5. 出库过程
    一个MQ异步解耦的任务队列,这个过程是扣除mysql库存
  • 如果扣mysql库存成功,出库成功,完成下订单整个流程,进入发货状态
  • 如果扣mysql库存失败,出库失败,进行一系列的操作
    • 订单状态改成取消
    • 返还redis库存
    • 退款

redis库存和mysql库存

支付前是预扣,是扣redis库存,是锁定库存的过程
支付后是真正扣,扣mysql库存 즉, 주문 서비스는 외부 세계로 메시지를 보냅니다. 제가 주문을 생성하면 MQ에서 메시지를 구독하는 서비스로 전달됩니다.

상품 서비스에서 주문 생성 메시지를 받으면, 공제 재고 작업이 실행됩니다. 일부 불가항력 요인으로 인해 재고 차감이 실패할 수 있다는 점에 유의하세요. 성공 또는 실패에 관계없이 제품 서비스는 재고 차감 메시지를 MQ로 전송하며, 메시지 내용은 재고 차감 결과입니다.
    주문 서비스는 다음 메시지를 받은 후 재고 차감 결과를 구독합니다.
  • 재고 차감이 성공하면 주문 상태가 Confirmed, 즉 주문으로 변경됩니다.
  • 재고 공제가 실패하면 주문 상태를 Cancelled로 변경하세요. 즉, 주문이 실패했음을 의미합니다. 안정적인 메시지 전달이 필요합니다. 서비스에서 보낸 메시지는 확실히 MQ에서 수신됩니다.

사용자 경험의 변화

프런트 엔드는 대기열 매체 인터페이스와 협력합니다.

제품/주문 서비스가 비동기화되어 플래시 세일 시나리오에 적합합니다. 트래픽이 크지 않을 때는 적합하지 않습니다.

🎜🎜비동기식 디자인🎜🎜🎜🎜인벤토리는 Redis에 저장됩니다🎜🎜요청을 받은 후 Redis는 재고가 충분한지 확인하고 Redis에서 해당 재고를 뺍니다🎜🎜주문 서비스는 주문을 생성하고 데이터베이스에 기록합니다. 그리고 메시지를 보냅니다🎜🎜🎜주문 결제가 성공하면 마지막으로 아웃바운드 과정이 있기 때문에 아웃바운드 과정이 실패할 수 있습니다. 🎜 인벤토리는 두 부분으로 구성됩니다. 🎜🎜🎜Cache Redis 계층 🎜🎜Database mysql 계층 🎜🎜🎜🎜고객 서비스에서 5개의 인벤토리를 추가하면 캐시 Redis와 데이터베이스 mysql 계층 모두 분산 트랜잭션의 최종 일관성을 사용하여 5개의 인벤토리를 추가해야 합니다. 만족: 모든 인벤토리가 추가되거나 아무것도 추가되지 않습니다. 🎜🎜주문이 생성되면 Redis 인벤토리가 먼저 차감됩니다. 차감이 성공하면 결제를 위한 주문이 생성됩니다. . 🎜🎜레디스 재고 차감시 상품 주문이 불가하며, 주문 실패로 인해 외층이 차단됩니다. 🎜🎜2단계 redis 인벤토리 공제 성공 후 주문 생성, 결제, 결제 성공 후 내 주문 센터로 돌아가면 아웃바운드 프로세스가 있는 것을 확인할 수 있습니다. 🎜🎜아웃바운드 프로세스🎜 MQ 비동기 분리 작업 대기열 이 프로세스는 mysql 인벤토리 공제입니다. 🎜🎜🎜🎜mysql 인벤토리가 성공적으로 공제되면 아웃바운드 프로세스가 성공한 것입니다. .주문 전 과정을 완료하고 배송상태를 입력하세요🎜🎜mysql 재고 차감에 실패하여 배송이 실패하면 일련의 작업이 수행됩니다🎜🎜주문 상태가 취소됨으로 변경됩니다🎜🎜redis 재고 반납 🎜🎜Refund🎜🎜🎜🎜🎜🎜redis Inventory 및 mysql Inventory🎜🎜🎜결제 전 잠금 처리되는 redis 인벤토리 차감withholding입니다. Inventory🎜 결제 후에는 실제 공제인 mysql 인벤토리 공제를 통해 인벤토리가 결국 일관성을 유지하도록 합니다🎜🎜그러나 극단적인 경우에는 데이터 불일치가 발생할 수 있습니다🎜🎜🎜redis 인벤토리 = mysql 인벤토리인 경우, 문제 없을 겁니다🎜🎜redis 인벤토리 mysql 인벤토리라면 과매도가 되고, 과매도 주문은 배송 과정에서 실패하게 됩니다🎜🎜🎜이렇게 하면 전체적으로 배송이 되지 않습니다. 문제인 mysql 데이터베이스 레이어는 결국 재고에 문제가 없도록 보장합니다. 🎜🎜🎜질문🎜🎜

데이터베이스 인벤토리와 Redis 인벤토리가 일치하지 않습니다. 이를 감지하는 방법은 무엇입니까?

일치하지 않는 경우 동기화 방법

아직 좋은 계획이 떠오르지 않았습니다
더 폭력적인 방법은 새벽 1시 등 피크 시간대를 찾아 주기적으로 강제 취재를 실시하는 것입니다. 그러나 극단적인 경우에는 동기화 후에도 여전히 부정확성이 있을 수 있습니다. 예를 들어 동기화 과정에서 주문이 성공적으로 결제된 후 아웃바운드 프로세스에서 MySQL 재고가 차감됩니다. Redis 인벤토리는 차감되지 않습니다.

이것은 데이터베이스 동기화 캐시의 업데이트 메커니즘 문제입니다
일관된 논리적 설계의 문제입니다
缓存数 = 数据库库存数 - 待扣数
물론 다른 해결 방법도 있으며 일관성 요구 사항 수준을 고려하면 가능합니다. 간단하거나 복잡한 것을 사용하십시오. 솔루션은 시스템의 복잡성에 따라 다릅니다. 예를 들어 공제할 숫자는 대기열이나 캐시에 배치될 수 있습니다.
예를 들어, 결제하고 발송할 수량은 일반적으로 많지 않습니다. 일반 시스템은 데이터 링크에 오류가 발생하지 않는다는 것을 완전히 보장할 수는 없지만 보상이 있어야 합니다. 즉, 오류를 수정할 수 있습니다
예 오류가 없음을 보장하는 비용은 분명히 너무 높습니다
동기화에는 새로 고침 메커니즘이 있습니다. 예약되거나 MQ를 통해 또는 불일치 및 동기화 모니터링 등을 수행합니다. . .
캐시된 데이터의 최신성 보장이라고도 합니다.
일반적으로 너무 오래 걸리지 않으며 30분 또는 몇 분이 걸릴 수 있습니다. 시나리오에 따라 요구 사항이 다릅니다.


12306

12306 기차표를 구매하는 사람은 그럴 수 없습니다. 야간 티켓 구매, 이번에는 재고 동기화, 데이터베이스 재고를 Redis 재고와 동기화하는 것으로 예상되지만 기차표 구매시 주문이 생성되기 전에 실제 재고를 차감해야합니다. 즉, mysql 재고를 차감해야하며,

기차표를 구매하기 때문에 쇼핑은 결제 후 배송이 가능하지만, 티켓의 경우 결제 전 창고에서 출고하셔야 하기 때문에 배송이 성공적으로 이루어져야 주문이 가능합니다. Redis 인벤토리도 도입해야 합니다

먼저 캐시에 있는 인벤토리를 공제하고 나면 mysql에서 인벤토리를 공제할 수 있습니다.

캐시 내 인벤토리 차감에 실패하면 차단되며 부족한 인벤토리가 반환됩니다. 이러한 요청은 mysql에 펑처링되지 않아 대부분의 요청 압력을 차단합니다.

Redis 인벤토리가 mysql 인벤토리와 일치하지 않을 수 있습니다. 극단적인 경우에는 반드시 가능하며 인벤토리 동기화가 필요합니다.

캐시 인벤토리가 데이터베이스 인벤토리보다 많으면 티켓이 나타납니다. 쿼리에 있지만 주문을 할 수 없습니다. 이 경우에는 데이터베이스에 과도한 부담이 발생합니다. 그러나 12306은 이 문제를 방지할 수 있는 다른 방법이 있어야 합니다. , 문의했을 때 티켓이 있었지만 단일 상황이 발생하지 않았습니다.
  • 캐시 인벤토리가 데이터베이스 캐시보다 적으면 문제가 없을 것입니다. 티켓만 있고 판매는 없을 것입니다. 인벤토리 동기화가 완료되면 내일 다시 정확해질 것입니다.

위 내용은 Redis 인벤토리 과매도 문제 해결의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:csdn.net
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!