Home  >  Article  >  Database  >  Solving the problem of oversold inventory in Redis

Solving the problem of oversold inventory in Redis

coldplay.xixi
coldplay.xixiforward
2021-03-18 10:49:422857browse

Solving the problem of oversold inventory in Redis

Use MQ between the product and the order service

When the inventory of the product service changes, the order service inventory is notified through MQ Variety.

Original synchronization process

  1. Query product information (call product services)
  2. Calculate total price (generate order details)
  3. Commodity service deducts inventory (calls commodity service)
  4. Order warehousing (generates order)
// 原始的MySQL同步流程// 判断此代金券是否加入抢购SeckillVouchers seckillVouchers = seckillVouchersMapper.selectVoucher(voucherId);AssertUtil.isTrue(seckillVouchers == null, "该代金券并未有抢购活动");// 判断是否有效AssertUtil.isTrue(seckillVouchers.getIsValid() == 0, "该活动已结束");// 插入数据库seckillVouchersMapper.save(seckillVouchers);

Recommendation (free): redis

Deduct inventory directly when an order is generated. This is the most original inventory deduction plan. It is relatively simple, but there are

problems

  • It may cause many orders to deduct product inventory without payment. This requires a background script to release the inventory of orders that have not been paid for a period of time and cancel the order.
  • Deduct inventory immediately , Concurrency difference

1. 3-step product service, operating the db of the product service, 2. 4-step order service, operating the db of the order service.

Avoid accessing the db of different services. In principle, the same service can only operate the db of its own service.

MQ Asynchronousization

First consider only making step 4 asynchronous.

Analysis

2 and 4 are all operations on the db. Step 4 does not wait. Feedback will be given to the user immediately after the success of steps 1, 2, and 3.

After that, the order will be placed asynchronously through the message notification service. If the asynchronous order placement in step 4 fails, the operation will be retried and the order will be regenerated. The MQ message can also be traced back.

After the order is created, it is in the queue state, and then the service publishes an event Order Created to the message queue.
That is, the order service sends messages to the outside world: I create an order, which is forwarded by MQ to the service that subscribes to the message.

If the product service receives the order creation message, it will perform the inventory deduction operation. Note that the inventory deduction may fail due to some force majeure factors. Regardless of success or failure, the product service will send an inventory deduction message to MQ, and the content of the message is the result of the inventory deduction.
The order service will subscribe to the result of inventory deduction. After receiving the message:

  • If the inventory deduction is successful, the order status will be changed to Confirmed, that is, the order will be placed. Success
  • If the inventory deduction fails, change the status of the order to Cancelled, that is, the order failed

To achieve the above model requirements, reliable information is required Delivery. Messages sent by the service will definitely be received by MQ.

  • Changes in user experience
    The front end cooperates with the queuing medium interface.

Commodities/order services have become asynchronous, which is suitable for flash sale scenarios. It is not very suitable when the traffic is not large.

Asynchronous design

  1. Inventory is saved in Redis
  2. After receiving the request, Redis determines whether the inventory is sufficient and subtracts the inventory in Redis
  3. The order service creates an order and writes it into the database, and sends a message

When the order payment is successful, there will be an outbound process. Since there is this process, the outbound delivery may fail.
The inventory has two parts:

  • Cache redis layer
  • Database mysql layer
  1. When customer service adds 5 new inventories, then Both the cache redis and database mysql layers need to add 5 inventories, and use the final consistency of distributed transactions to meet the requirements: either all inventories are added, or none are added.
  2. When the order is generated, the inventory needs to be deducted. Deduct the redis inventory first. If the deduction is successful, an order is generated for payment. This process does not deduct the mysql inventory.
  3. When the redis inventory is deducted, the product cannot be ordered, and the order will fail, so the outer layer is blocked.
  4. In step 2After successfully deducting the redis inventory, generate the order, make the payment, the payment is successful, return to my order center, and you will find that there is an outbound process.
  5. Outbound process
    An MQ asynchronously decoupled task queue, this process isdeduction of mysql inventory:
  • If the deduction of mysql inventory is successful and the shipment is successful, the entire order process is completed and the delivery status is entered.
  • If the deduction of mysql inventory fails and the shipment fails, a series of operations are performed
    • Order The status is changed to canceled
    • Return redis inventory
    • Refund

##redis inventory and mysql inventory

Before payment is

withholding, it is deduction of redis inventory, which is the process of locking inventory After payment, it is real deduction,
deduction of mysql inventory, Ensure that the inventory is eventually consistent

However, in extreme cases there will be data inconsistencies

    If redis inventory = mysql inventory, there will be no problem
  • If redis inventory< ; In mysql inventory, there will be no oversold problem, but there will be situations where there is actual inventory but no sales.
  • If redis inventory > mysql inventory, it will be oversold, and oversold orders will be shipped out of the warehouse. It will fail during the process
This way there will be no problems overall, and the mysql database layer will ensure that there will be no problems with the inventory in the end.

question

The database inventory and redis inventory are inconsistent, how to detect it?

If inconsistency is detected, how to synchronize

I haven’t come up with a good plan
A more violent method is to find a low peak period, such as At 1 o'clock in the morning, periodic forced coverage. However, in extreme cases, there may still be inaccuracies after synchronization. For example, during the synchronization process, there happens to be an order being paid. After the order is successfully paid, the MySQL inventory is deducted during the outbound process, but the Redis inventory is not deducted.

This is a problem with the update mechanism of the database synchronization cache
It is a problem of consistent logical design
Cache number = Database inventory number - Number to be deducted
Of course, there are other solutions, and considering the consistency requirements, you can use simple or complex solutions
It depends on the complexity of the system. The larger the system, the more detailed it must be broken down
For example The number to be deducted can be placed in a queue or cache, and there is a count at the same time. Just read the count directly.
For example, if it is placed in mongo, the quantity that has been paid and is to be shipped out is generally not very large. Just count it and it will be fine. Not much will be lost
Therefore, general systems cannot completely guarantee that the data chain will not make errors, but there must be compensation, that is, errors can be corrected
The cost of ensuring that there are no errors is obviously too high
There is a set of synchronization The refresh mechanism can be scheduled, or it can be through MQ, or it can monitor different times and synchronize it, etc. . .
Also called ensuring the freshness of cached data
Generally it won’t take too long, maybe half an hour or a few minutes. Different scenarios have different needs

12306

12306 for buying train tickets, you cannot buy tickets at night. This time is probably to synchronize the inventory and synchronize the database inventory to the redis inventory. However, when buying train tickets, the actual amount must be deducted before the order is generated. Inventory, that is, the inventory of mysql needs to be deducted.

Because buying a train ticket is different from shopping. Shopping can be shipped out of the warehouse after payment, but buying a ticket must be shipped out of the warehouse before payment. Therefore, the outgoing inventory must be deducted from the inventory. The warehouse process is advanced. Only when the warehouse is successfully shipped can an order be generated. It is also necessary to introduce redis inventory.

The inventory in the cache must be deducted first. After the deduction is successful, the inventory in mysql can then be deducted.

If the inventory in the cache fails to be deducted, it will be blocked out and insufficient inventory will be returned. These requests will not be punctured into mysql, blocking most of the request pressure.

The redis inventory will be inconsistent with the mysql inventory. In extreme cases, there must be some, and inventory synchronization is required.

  • When the cache inventory is higher than the database inventory If there are too many, then it will appear that there are tickets in the query, but the order cannot be placed. When placing the order, it is said that the inventory is insufficient. In this case, it will cause excessive pressure on the database. However, 12306 should have other means to avoid this problem, but , I have indeed encountered a situation where I had tickets when I checked, but could not place an order.

  • When the cache inventory is less than the database cache, there will be no problem. There will only be tickets but no sales. After the inventory synchronization is completed, it will be accurate again tomorrow.

The above is the detailed content of Solving the problem of oversold inventory in Redis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete