当前位置:网站首页>How to avoid placing duplicate orders

How to avoid placing duplicate orders

2022-06-24 14:17:00 JackieZhengChina

A very basic problem of electronic trading , It's about avoiding repeat orders . Users want to buy it once , As a result, I got two orders . If you don't find out in time , Will bring additional logistics costs and wrangle . It's not good for the reputation of the business .

Technically , This is a Distributed Consistency issues ; But actually , Technology cannot 100% Solve these kinds of problems , It has to be dealt with in a variety of ways . Let's talk about it here .

Why is it so heavy ?

  • reason 1: client bug

For example, the key to place an order is pressed , Before receiving the server request , The status of the key is not set to Has been disabled state , It can also be pressed . Or, , Under the touch screen , The touch of a user's finger may be recognized as multiple clicks by the mobile phone operating system .

Um. , Who can guarantee that the client doesn't occasionally give something bug Well .

  • reason 2: Overtime

There may be an unstable network between the user's device and the server . Such an order request goes by , Return doesn't have to come back . The biggest problem with overtime is : From the user's point of view , He can't be sure that the order request hasn't arrived at the server yet , It's still on the server, but the return is lost .—— Users can't tell whether the order has been placed or not .

So after waiting for a timeout ,UI The user may be prompted to place an order over time , Please try again .

Order timeout

  • reason 3: User App Flash back / Manual forced retreat , Then open it again and place an order again

Maybe we can use some technical means to avoid users placing duplicate orders , But anxious users may restart the process / restart App/ Restart the phone . Under this compulsion , Any technology will fail —— Users won't let your technology execute at all , How do you play ?

under such conditions , How to prevent users from placing an extra order ?

Use idempotent to prevent duplicate orders

In terms of Technology , It's a distributed consistency issue , That is, whether an order is successful on the client and server / Failure, agreement . The key to prevent duplicate orders is Use a client generated , Can be used to avoid repetition key, Be commonly called dedup key(deduplicate key The meaning of ). This key It can be generated in any way that can guarantee global uniqueness , such as uuid. Clients and servers need to use this dedup key As a series condition , Solve the problem of weight removal together .

The client process

The client needs to implement such a single interface . The user clicks 【 Confirm the order 】 when , It should produce a unique dedup key, The order data is sent to the server . Before the server returns , The interface should be waiting , Until the server responds successfully / Failure or timeout ( such as 15 Seconds later , No server response received ). If a timeout occurs , The user should be prompted to try again or exit the interface . When the user clicks 【 retry 】 when , You should use the just generated dedup key To send the order request again —— If the user does not exit the process all the time , Try again every time the user clicks , We should all use this dedup key To try again , Until the server returns normally , Or the user gives up and returns .

The client process of placing an order

Back end data table design

The back end is in the order data table , Need to increase the dedup_key This column , And set up Unique constraint .

 

create table order(
  # ...
  dedup_key varchar(60) not null comment 'key to pretend order duplication',
  # ...
  unique uniq_dedup_key(dedup_key)
);

The realization of the order

When implementing the order logic , Based on this dedup_key Achieve one "create-or-get" Semantic interface —— In short, it is

 

 If specified dedup_key The order already exists for , Then return directly ; otherwise , Use this dedup_key Place an order .

In pseudocode, it's about :

 

@Transactional
Order createOrder(Integer userId, String prodCode, Decimal amount, String dedupKey) {
  try {
    String orderId = createOrder(userId, prodCode, amount, deupKey); // insert a new order
    Order order = getOrderById(orderId); // read order from db
    order.setDuplicated(false);
    return order;
  } catch(UniqueKeyViolationException e) {
    // if duplicated order has existed
    Order order = getOrderByDedupKey(dedupKey);
    order.setDuplicated(true);
    return order;
  } catch (Exception e) {
    // hanlde other errors and rollback transaction ...
  }
}

At this time , This order code always returns an order ( Unless something happens DB Hang up or something ), Or it's new , Or it's an existing single . Be careful , It's better to add an attribute to the order ( For example, in the example “duplicated”) To indicate that this order is newly generated this time , Or is it returned directly because of idempotence . In this way, the front end can prompt different copywriters for these two situations .

Is technology enough to deal with idempotent ?

The above process does not consider a situation , That is, the user is forced to quit the client halfway , Or click directly 【 return 】 Back to the product page , Go through the order process again . At this time, the client cannot judge whether the user wants to place a new order , I still want to place an order for the second time . here , We can consider it from the product design .

such as , Cache a table on the client side , Record all orders without confirmation results .

  Product code Product quantity amount of money dedup key
Unconfirmed order 1AAA11000xxx-yyy-zzz
Unconfirmed order 2BBB2500.00Aaa-bbb-ccc
...    

Through this table , We can guess Let's look at the user's intention . such as , If the user re submits an order , Its product code 、 The amount is exactly the same as one recorded in the table , You can prompt the user :

Prompt whether the user has lowered the weight

If the user wants to try again , You can continue to use the corresponding record in the table dedup key Re launch order .

This is not absolutely accurate , Just try to reduce the possibility of user misoperation . Of course , Product design can be simplified for user interaction , Not necessarily . This requires other mechanisms to cooperate , such as “ notice ”.

notice

Once the server orders successfully , Through some kind of notification mechanism ( Such as APNS、Websocket) Actively push the order to the client , Force the client to pull the latest order information again , And cooperate with “ Unconfirmed order ” surface , To inform Badge/ Pop box and other ways to prompt the user that an order with unknown status has just been successful / failed .

Another way is , The server scans users' order data in real time , Once a possible duplicate order is found , Call the customer service immediately Take the initiative Contact users , Deal with the problem in time .

If it doesn't stop ……

After layers of obstruction , There may still be user misoperation , I didn't find the weight until I received two copies of the goods . At this point, we have to rely on operations / Customer service support . Provide the means for users to appeal , Ask the user to ask which orders are duplicate , And by the sales system store 、 The supplier and the Buyer negotiate how to deal with it according to the user's operation record . We need technology to help minimize the chance of this kind of manual processing . Because each treatment will cost a lot of labor , And some operating expenses ( Like reparations 、 Small gifts and so on ).

So much trouble , Is it necessary ?

It's divided into business scenarios , It may not be necessary for many e-businesses . Because it takes a certain amount of time from the time the user places an order to the time when the order is approved to the time when the order is delivered ( It could be half an hour ~1 Hours ), And the next step of the process will be started only after the payment is successful . At this time , The probability of users recovering from network errors , Distinguish whether it's heavy or not . Cooperate with customer service to actively prompt , Will greatly reduce the probability of problems .

But for financial services , This kind of weight removal is very necessary . because

  • “ Place an order + payment ”. Users often buy financial management “ Place an order + payment ” Do it together , You can't order alone / Pay separately
  • The user's income may be very large . Tens of thousands, for example , Hundreds of thousands
  • Loss of accuracy . If once it's loaded , It may affect the accuracy of investment fund allocation of users .
  • Difficult to withdraw . Some financial products have the problem that orders cannot be cancelled ; Or even if it's withdrawn , Money can't be paid back immediately . Wait until the payment is collected , Maybe this purchase opportunity is wrong . For example, for fund trading , miss 1 A trading day , The price will change .

Based on these characteristics , In financial products , We have to do our best to get rid of it .

Conclusion

The above is a general way to deal with the problem of duplicate orders . You can notice , No matter how good the technology is , It's impossible 100% All the possibilities , Must rely on technology + The product design + Operational support Only by comprehensive means can we solve such problems .

in addition , This article is not about order payment yet ( Payment may also be repeated ) Further complexity , There is no discussion about performance optimization in the case of high concurrency , Just talking about the order itself . So you can imagine that the real trading business is much more complicated than what is said here .

The principle introduced in this paper is not only applicable to preventing repeated orders , It can be applied to any need “ Create a resource that should not be duplicated ” Scene , such as “ Send a notification to the user ”,“ Trigger a batch task that cannot be repeated “……


link :https://www.jianshu.com/p/e618cc818432

 

Other relatively simple but imperfect solutions

For example, the client and the server do not have a unique identifier for the request , This is how to solve the problem of repeated orders ?

1 The client starts the request after the user clicks the button , The button should be set as unavailable

2 In the process of server-side processing , Lock it , If it is a single instance, add a local cache lock , It is better to add distributed locks to multiple instances

Part of the code is as follows :

 var isdoing = Gd.CacheApi.UserCapital.GetUserConsumeLockCache(userId);
                    if (isdoing < 1)
                    {
                        // Lock 
                        Gd.CacheApi.UserCapital.SetUserConsumeLockCache(userId);
 
                        var result = UserConsume(userId, consumeTypeId, consumeMoney, isAnonymous, wishContent, consumeNums, isShowWish, toUserName);
                        call.Result = result;
                        if (result.ResultCode != 0)
                        {
                            call.Error = result.ResultMsg;
                        }
                        else
                        {
                            call.Error = "";
                        }
                        // Remove lock 
                        Gd.CacheApi.UserCapital.RemoveUserConsumeLockCache(userId);
                    }

This method can effectively reduce the occurrence of duplicate orders , But it's not perfect , The above scheme is relatively perfect !

--- end ---


 


---------------------
author :Jack2013tong
source :CSDN
original text :https://blog.csdn.net/huwei2003/article/details/105712692
Copyright notice : This is the author's original article , Please attach a link to the blog post !
Content analysis By:CSDN,CNBLOG One click reprint plugin for blog posts

原网站

版权声明
本文为[JackieZhengChina]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/175/202206241207599196.html