Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to solve the accident caused by duplicate order number

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the relevant knowledge of "how to solve the accident caused by the repetition of order number". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

We had an accident online, and the appearance of the accident was as follows:

Two identical order numbers appear in the system, but the content of the order is not the same, and the system keeps throwing errors when querying according to the order number, and there is no normal callback, and things have happened more than once. so this system upgrade must be solved.

The colleague who handled it has changed it several times before, but the effect is not good all the time, and there will always be the problem of duplicate order number, so I took advantage of this problem to sort out the code written by my colleague.

Here's a brief look at the code at that time:

/ * * OD order number generation * order number generation rules: OD + yyMMddHHmmssSSS + 5 digits (merchant ID 3 digits + random number 2 digits) 22 digits * / public static String getYYMMDDHHNumber (String merchId) {StringBuffer orderNo = new StringBuffer (new SimpleDateFormat ("yyMMddHHmmssSSS") .format (new Date () If (StringUtils.isNotBlank (merchId)) {if (merchId.length () > 3) {orderNo.append (merchId.substring (0mem3));} else {orderNo.append (merchId);}} int orderLength = orderNo.toString (). Length (); String randomNum = getRandomByLength (20-orderLength); orderNo.append (randomNum) Return orderNo.toString ();} / * * generate a random number of specified digits * * / public static String getRandomByLength (int size) {if (size > 8 | | size9990) {SEQ.getAndSet (1000);} return dataTime.format (DF_FMT_PREFIX) + SEQ.getAndIncrement ();}

Of course, once the code has been written, you can't end it so casually. Now you have to go to a test main function to see:

Public static void main (String [] args) {List orderNos = Collections.synchronizedList (new ArrayList ()); IntStream.range (0Jing 8000). Parallel (). ForEach (I-> {orderNos.add (generateOrderNo ());}); List filterOrderNos = orderNos.stream (). Distinct (). Collect (Collectors.toList ()); System.out.println ("generated orders:" + orderNos.size ()) System.out.println ("number of orders after filtering duplicates:" + filterOrderNos.size ()); System.out.println ("number of repeat orders:" + (orderNos.size ()-filterOrderNos.size ();} / * * Test results: number of orders generated: 8000 orders after filtering duplicates: 8000 number of repeat orders: 0 * /

That's great. I succeeded at once, and I can go online directly.

However, looking back at the above code, although it has solved the problem of concurrent order number duplication to the greatest extent, there is still a potential danger for our system architecture: is it impossible to repeat if there are multiple instances (clusters) in the current application?

In view of the need for an effective solution to this problem, I thought: how to distinguish the order number of multiple instances?

The following is the general direction of my thinking:

Use UUID (initialize one the first time the order number is generated)

Use redis to record a growth ID

Maintain a growing ID using database tables

The network IP where the application is located

The port number where the application is located

Use third-party algorithms (snowflake algorithm, etc.)

Using process ID (which is a viable option to some extent)

After thinking about it, our application runs in docker, and the application port in each docker container is the same, but the network IP does not have the problem of repetition, and there is also the possibility of repetition of the process. For the way of UUID, we have suffered losses before. Far away, redis or DB is also a better way, but it is less independent.

At the same time, another important factor is that all applications related to order number generation are on the same host (linux physical server), so I choose IP for the current system architecture.

Here is my code:

Import org.apache.commons.lang3.RandomUtils; import java.net.InetAddress; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.IntStream Public class OrderGen2Test {/ * * order number generation * * / private static ZoneId ZONE_ID = ZoneId.of ("Asia/Shanghai"); private static final AtomicInteger SEQ = new AtomicInteger (1000); private static final DateTimeFormatter DF_FMT_PREFIX = DateTimeFormatter.ofPattern ("yyMMddHHmmssSS"); public static String generateOrderNo () {LocalDateTime dataTime = LocalDateTime.now (ZONE_ID) If (SEQ.intValue () > 9990) {SEQ.getAndSet (1000);} return dataTime.format (DF_FMT_PREFIX) + getLocalIpSuffix () + SEQ.getAndIncrement ();} private volatile static String IP_SUFFIX = null; private static String getLocalIpSuffix () {if (null! = IP_SUFFIX) {return IP_SUFFIX } try {synchronized (OrderGen2Test.class) {if (null! = IP_SUFFIX) {return IP_SUFFIX;} InetAddress addr = InetAddress.getLocalHost () / 172.17.0.4 172.17.0.199, String hostAddress = addr.getHostAddress (); if (null! = hostAddress & & hostAddress.length () > 4) {String ipSuffix = hostAddress.trim () .split ("\\.") [3] If (ipSuffix.length () = = 2) {IP_SUFFIX = ipSuffix; return IP_SUFFIX;} ipSuffix = "0" + ipSuffix; IP_SUFFIX = ipSuffix.substring (ipSuffix.length ()-2) Return IP_SUFFIX;} IP_SUFFIX = RandomUtils.nextInt (10,20) + "; return IP_SUFFIX;}} catch (Exception e) {System.out.println (" failed to get IP: "+ e.getMessage ()) IP_SUFFIX = RandomUtils.nextInt (10jue 20) + "; return IP_SUFFIX;}} public static void main (String [] args) {List orderNos = Collections.synchronizedList (new ArrayList ()); IntStream.range (0L8000). Parallel (). ForEach (I-> {orderNos.add (generateOrderNo ());}) List filterOrderNos = orderNos.stream (). Distinct (). Collect (Collectors.toList ()); System.out.println ("sample order:" + orderNos.get (22)); System.out.println ("number of orders generated:" + orderNos.size ()); System.out.println ("filter repeat orders:" + filterOrderNos.size ()) System.out.println ("repeated orders:" + (orderNos.size ()-filterOrderNos.size ();}} / * * sample orders: 20082115575546011022 generated orders: 8000 after filtering duplicate orders: 8000 repeated orders: 0 * /

Finally, the code description and some suggestions

There is no need for locking in the generateOrderNo () method, because CAS self-rotation locks are used in AtomicInteger (to ensure both visibility and atomicity, please learn for yourself)

There is no need to synchronize logic that is not null in the getLocalIpSuffix () method (two-way check lock, which is a safe singleton mode as a whole)

The way I implement is not the only way to solve the problem, the specific solution to the problem needs to be based on the current system architecture.

Any testing is necessary, my colleagues did not self-test after the previous attempts to solve this problem, not testing is detrimental to development professionalism!

This is the end of the content of "how to solve the accident caused by the repetition of order number". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report