Optimistic locking causes concurrency failure solution

Business scene

When a user pays a merchant with Alipay or WeChat, after the payment is successfully recalled, the merchant's balance needs to be modified, and running water will be generated. Due to the concurrent situation of multiple users paying at the same merchant, @version optimistic lock is used to prevent confusion of merchant balance information. However, in the case of concurrency, optimistic lock can only ensure that the data is not chaotic, but cannot guarantee the normal operation of the business, because The user has successfully paid, and the user cannot be informed that the payment failed because the optimistic lock failed to generate the flow or the balance failed. At this time, it is necessary to solve the concurrency situation to successfully generate the flow and modify the balance.

Solution one

Based on the optimistic lock, the synchronization lock is synchronized. For the detailed functions of the synchronization lock, please refer to the blog written by others, such as http://blog.csdn.net/luoweifu/article/details/46613015
The pseudo code is as follows:

//因为多个站的并发不受影响,所以只需要考虑多个用户在同一用户的同步锁就ok
//选取油站的id作为同步锁的条件,并选用字符串的intern()方法
synchronized (merchant.getId().intern()){
    //产生流水
    //修改该商户的余额
}

Regarding the intern() method, it is a String pool controlled by the class. If the String exists in the pool, the String will be returned. If not, the String will be created in the pool and returned. For details, see the source code.

    /**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */
    public native String intern();

Solution two

Write the modified balance and the generated flow in the same transaction. Once an exception occurs, use the transaction to roll back and re-run the entire transaction again until the operation is successful. Since I am using Option 1, Option 1 will not be discussed in detail. When checking the information, there are several blogs that have introduced them,
such as: https://gist.github.com/crazycode/4970741 , and
also said to use AOP, http://blog.csdn.net/zhanghongzheng3213/article/details/50819539

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325521488&siteId=291194637