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
// 原始的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
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:
Confirmed
, that is, the order will be placed. SuccessCancelled
, that is, the order failedTo achieve the above model requirements, reliable information is required Delivery. Messages sent by the service will definitely be received by MQ.
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
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:
Deduct the redis inventory first
. If the deduction is successful, an order is generated for payment. This process does not deduct the mysql inventory
. After 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. Outbound process
deduction of mysql inventory
:##redis inventory and mysql inventory
Before payment iswithholding, 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
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 designCache 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!