1. Why is idempotent needed?
In a distributed scenario, it is extremely difficult to implement a strongly consistent protocol among multiple business systems. One of the simplest and achievable assumptions is to ensure eventual consistency, which requires the server to give the same response when processing a repeated request, and will not have side effects on persistent data (ie, multiple operations versus single operations). The results need to be consistent from a business perspective).
If an API is idempotent, the call originator can safely retry. This is in line with our general assumption.
Providing idempotent capabilities is what service providers need to do, so this article is written from the perspective of service providers, that is, "we" below usually refers to service providers.
2. How to make idempotent judgment
So how do we make an idempotent judgment for a request? First of all, we need a way to distinguish what is a "one-time" request. Second, according to the difference in the way of persisting data in the API implementation logic, we also need different judgment methods.
2.1 Request Unique ID
Usually our API needs to add an attribute that can identify the uniqueness of the request, such as bizId, which is used by the calling initiator to identify a unique business requirement considered by the business. It must be noted that it is a "business unique identifier", not a technical unique identifier, there is an essential difference between the two.
Fact 1 : However, in most cases, the call originator may not know how to generate a valid request unique identifier, which requires us to have more communication in the process of business docking.
2.2 How long does it take to be idempotent
Being idempotent means that we must have persisted some data, but any data cannot exist forever, and it will require a validity period.
For most requests, recommends that the idempotent validity period is three months . Some special scenarios can even be a year. But hardly any longer.
The validity period is a clear contract, which means that we can periodically do some data governance work on persistent data, and at the same time, requests that exceed the validity period will basically fail idempotent, then its consequences are "the same thing, in a few months. Then did it again."
2.3 Write type
If our business logic is to write something in persistent storage, then the best practice is to add a unique key, which usually consists of user_id, operation type, biz_id . The operation type is the business operation type defined by our system design, plus it is to avoid mutual interference between different operation types. Adding user_id is because usually we will sub-database and sub-table.
For scenarios that both write and update data, inserts need to be put in the front, otherwise idempotency may not work. For example, in the following inventory operation scenario, if the two SQLs are written in reverse, they cannot be idempotent in the scenario of inventory sales:
insert 库存扣减流水;
update 库存 set 库存可用数=库存可用数-1 where 库存id=? and 库存可用数>0;
When the unique key conflicts, we need to capture it, which is likely to be idempotent. Why is it a high probability and not a certainty? This is because of the aforementioned "fact 1" in advance. The caller may have reused the request unique number incorrectly, and may have changed some core parameters when retrying.
Therefore, we need to do the following when a unique key conflict occurs:
- queries the previously written data according to the unique key .
- to check the key information . For example, the API we provide is to issue coupons, then we need to verify at least these information: receiving user ID, coupon template, coupon denomination, validity period, etc. When the key information is inconsistent, an error code similar to " DUPLICATE_BUT_DIFFERENT_REQUEST " is returned; when the verification is passed, the successfully sent coupon ID is returned. This is very important. Returning idempotent success without verifying key information is the root cause of failures in most scenarios.
2.4 Update
The biggest challenge of the update type is that we have no place to store multiple update behaviors for a piece of data, so in most cases, we need to use a state machine to speculate whether an update behavior has occurred. More complex situations may require us to add dedicated Idempotent table.
2.4.1 Using State Machines
Most of the data processing in business is stateful, such as transaction orders. The preferred method at this time is to use the sequence of the state machine to determine whether an update behavior has been done. However, this is not simple. We need to be very careful to look at the various rules and restrictions in the business. At the same time, in addition to updating the status, in most cases, some additional information will be updated along with the update. We also need to check Whether the additional information has been updated as requested by the request.
2.4.2 Add idempotent table
By adding an idempotent table, the update type is transformed into the write type described in Section 2.3. However, it should be noted that the idempotent table needs to be in the same transaction as the currently updated table, otherwise it will be invalid.
The idempotent table needs to add a field indicating the time of data writing/update, which is convenient for us to regularly clean up expired data.
2.5 Delete type
It is recommended to use logical deletes instead of physical deletes on the storage, so that we have a way to tell if the delete operation has been done. Deletion often means that the data is in the final state, so it is also the best to deal with idempotent; if the deletion is not the final state of the data in the business design, then you need to be very careful, because it violates the general design principles.
3. Summary
Idempotency is arguably the cornerstone of distributed applications, and as you can see, implementing it is not as straightforward as most people first think. Doing it well requires us to design and think from the perspective of business semantics.
Text / Sumu
Pay attention to Dewu technology and be the most fashionable technical person
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。