제품과 주문 서비스 사이에 MQ를 사용하세요
제품 서비스의 재고가 변경되면 MQ를 통해 주문 서비스에 재고 변경 사항이 통보됩니다.
원래 동기화 프로세스
// 原始的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收到。
商品/订单服务都变成异步化,适合秒杀类场景,当流量不大时,并不太适合。
异步设计
当订单支付成功后,会有一个出库过程,既然有这个过程,就有可能出库失败。
库存有两部分:
先扣redis库存
,如果扣除成功,则生成订单进行支付,这个过程不扣除mysql库存
。扣除redis库存成功后
,生成订单,进行支付,支付成功,返回我的订单中心, 会发现有一个出库过程。出库过程
扣除mysql库存
:redis库存和mysql库存
支付前是预扣
,是扣redis库存
,是锁定库存的过程
支付后是真正扣,扣mysql库存
즉, 주문 서비스는 외부 세계로 메시지를 보냅니다. 제가 주문을 생성하면 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!