Service idempotence --- anti-duplication table

1. The problem of preventing table duplication

Another solution to prevent repeated submission of data is to implement an anti-duplication table. The idea of ​​anti-heavy watch is also very simple. First create a table as an anti-duplication table, and at the same time establish a unique index of one or more fields in the table as an anti-duplication field to ensure that there is only one piece of data under concurrent conditions. Insert data into the anti-duplication table before inserting data into the business table. If the insertion fails, it means duplicate data

Insert image description here
For the solution to the anti-heavy table, some people may say why not use pessimistic locking. Deadlocks may also occur during the use of pessimistic locks. Pessimistic locking is implemented by locking tables. Suppose now a user A accesses table A (table A is locked), and then tries to access table B; another user B accesses table B (table B is locked), and then tries to access table A. At this time, for user A, since table B has been locked by user B, user A must wait until user B releases table B before he can access it. At the same time, for user B, since table A has been locked by user A, user B must wait until user A releases table A before accessing it. At this point the deadlock has already occurred

2. Solution (select+insert anti-resubmission)

When the amount of concurrency is not high, the realization of idempotence is very simple, and idempotent control can be completed through the idea of ​​select+insert. Before the business is executed, first judge whether it has been operated, if not, execute it, otherwise it is judged as a repeated operation

Insert image description here

3. Implement ideas

When accessing concurrently, because the judgment is based on the id, the id value must be guaranteed to be unique when submitted multiple times. The access process is as follows and
Insert image description here
the code is as follows:

@Override
@Transactional(rollbackFor = Exception.class)
public String addOrder(Order order) {
    
    
    order.setCreateTime(new Date());
    order.setUpdateTime(new Date());
    //查询
    Order orderResult = orderMapper.selectByPrimaryKey(order.getId());
    Optional<Order> orderOptional = Optional.ofNullable(orderResult);
    if (orderOptional.isPresent()) {
    
    
        return "数据存在";
    }
    int result = orderMapper.insert(order);
    if (result != 1) {
    
    
        return "失败";
    }
    return "成功";
}

For the above solution, idempotence control cannot be achieved under concurrency. Through the jemeter test and simulating 50 concurrencies, it can be found that duplicate data has been inserted. Dirty data is generated. To solve this problem, it is very simple. Just add a unique index at the database level. Setting the id as a unique index is also the easiest way to think of it. Once the id is repeated, an exception will occur, which can also be solved by avoiding the occurrence of dirty data. Permanently idempotent. However, this solution cannot be used in the case of sub-database and sub-table. It is only applicable to the case of single table.

Guess you like

Origin blog.csdn.net/weixin_44702984/article/details/131610435