- vừa được xem lúc

Phân biệt Idempotency và Optimistic Locking

0 0 6

Người đăng: Nguyễn Đắc Khoa

Theo Viblo Asia

Gần đây mình nhận ra có khá nhiều người nhầm lần giữa hai khái niệm này và cho rằng có thể sử dụng Optimistic Locking để thực hiện Idempotency. Bài viết này mình muốn chỉ rõ đây là hai khái niệm khác nhau hoàn toàn và không nên nhầm lẫn.

1. Idempotency

Theo Wiki thì:

Idempotence is the property of certain operations in mathematics and computer science, that can be applied multiple times without changing the result beyond the initial application.

Một cách đơn giản thì một operation được coi là idempotent khi mà nó được gọi đi gọi lại nhiều lần thì vẫn không thay đổi kết quả của của hệ thống.

Ví dụ như HTTP GET method, khi bạn gọi 3 lần lấy status của 1 payment transaction kết quả vẫn trả về như nhau mà không ảnh hưởng trạng thái của system.

GET http://api.example.com/payment/status/12345

Kết quả luôn luôn là:

{ "transactionId": "12345", "status": "SUCCESS", "amount": 100.00
}

Nhưng với HTTP POST thì khác, nếu bạn call 3 lần api thanh toán thì sẽ có thêm 3 giao dịch thêm vào hệ thống.

 POST http://api.example.com/payment/charge Payload: { "userId": "56789", "amount": 100.00, "paymentMethod": "credit_card"
}

Kết quả sau mỗi lần call:

{ "transactionId": "67890", "status": "SUCCESS", "amount": 100.00
}

Tại sao xử lý Idempotency lại quan trọng?

Như ví dụ về HTTP POST ở trên, nếu chẳng may có lỗi trong quá trình xử lý làm cho 1 giao dịch của khách hàng bị gọi lại 3 lần.

Bạn mua 1 cuốn sách 300k nó charge cho gần 1 triệu T_T

Vậy là đã hiểu tại sao xử lý Itempotency lại quan trọng rồi nhé.

Việc handle idempotency là bắt buộc trong một số hệ thống yêu cầu độ chính xác cao. Có nhiều cách để handle nhưng bài viết này mình sẽ không đi sâu vào nó.

2. Optimistic Locking

Optimistic Locking được thực hiện theo cơ chế Compare and Swap (CAS), cụ thể hơn thì nó sẽ check trạng thái của data có bị thay đổi hay không (Compare) trước khi thực hiện thay đổi (Swap)

Một chút về database, Optimistic Locking đảm bảo data không bị ghi đè lên nhau khi nhiều thread cùng update chung 1 record, field 'version' thường được sử dụng để compare trạng thái

Lấy ví dụ đơn giản bạn mua 1 ly cafe 80k và thanh toán qua app ngân hàng, nếu tài khoản bạn có 100k thì sẽ trừ còn 20k, nếu bạn chỉ còn 50k thì .... COOK 😂. Code sẽ nhìn giống như này (psudocode):

SELECT balance, version FROM balance_tab WHERE uid=$uid; If ($balance > $price) { $new_balance = $balance - $price $version_new = $version + 1 } else { return “not enough balance”; } UPDATE balance_tab SET balance=$new_balance, version=$version_new WHERE uid=$uid AND version=$version

Như vậy có thể thấy Optimistic Locking không thực sự Lock mà nó chỉ compare trước trạng thái (version) nếu chưa bị ai update thì mới ghi vào, còn không sẽ ném lỗi. Lại hơi lan mang rồi 😂 Về Locking mình sẽ có bài viết riêng nhé

3. Optimistic Locking không phải là Idempotency

Có nhiều người đang nhầm lẫn về cái này nhưng:

Việc bạn sử dụng Optimistic Locking không có nghĩa API của bạn đã Idempotent

Cũng ví dụ về ly cafe 80k ở trên, trong trường hợp số tiền đã bị trừ vào tài khoản nhưng khi response lại găp Network Error, client sẽ thực hiện retry lần thứ 2, data flow sẽ như thế này:

Init: balance = 100k, version=10 Expect: balance = 20k, version = 11 Request #1:
version=10 ⇒ version=11 balance=100 ⇒ balance=20 ___
Response fail vì network error
___ Request #2 (client retry): version=11 ⇒ version=12 balance=20 ⇒ balance= -60k (tượng trưng thôi vì application sẽ ném lỗi ko đủ tiền)

Qua ví dụ có thể nói là chỉ sử dụng Optimistic Lock không làm cho API trở nên Idempotent được mà phải áp dụng thêm nhiều cách khác.

4. Kết luận

Idempotency và Optimistic Locking là hai khái niệm hoàn toàn khác nhau và không nên bị nhầm lần

Optimistic Lock sử dụng để tránh data bị ghi đè lên nhau (data race) nhưng nếu call 2 lần khác nhau thì nó vẫn update 2 lần. Còn Itempotency là để diễn tả việc 1 API có bị gọi 2 (hoặc nhiều lần) với cùng 1 payload thì data vẫn chỉ update 1 lần duy nhất.

Mặc dù vậy vẫn có có nhiều case apply Optimistic Locking có thể làm API Idempotent luôn, nhưng cần hiểu rõ bản chất là Optimistic Locking không phải là Idempotency

Nguồn tham khảo: https://zongwb.medium.com/optimistic-locking-idempotency-936b87d1adc0#:~:text=Conclusion-,Optimistic locking and idempotency are two distinct concepts.,must be implemented with care.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Flutter - GetX - Using GetConnect to handle API request (Part 4)

Giới thiệu. Xin chào các bạn, lại là mình với series về GetX và Flutter.

0 0 359

- vừa được xem lúc

API vs WebSockets vs WebHooks: What to Choose?

. Khi xây dựng bất kì một ứng dụng nào, chúng ta đều cần phải có một cơ chế đáng tin cậy để giao tiếp giữa các thành phần của nó. Đây là khi APIs, WebSockets và WebHooks được ứng dụng vào.

0 0 102

- vừa được xem lúc

Sử dụng Fast JSON API serialization trong Ruby on Rails

Ở bài viết này chúng ta sẽ thử tạo 1 project API sử dụng gem fast_jsonapi cho serializer. Đầu tiên là tạo một project API mới. $ rails new rails-jsonapi --database=postgresql --skip-action-mailbox --skip-action-text --skip-spring -T --skip-turbolinks --api. .

0 0 132

- vừa được xem lúc

Test thử ba loại API chụp màn hình Windows

Hiện tại, Windows cung cấp khoảng ba cách để chụp màn hình. Thế thì cái nào là nhanh nhất? Tôi muốn test thử từng cái.

0 0 71

- vừa được xem lúc

Ngừng sử dụng REST cho API — GraphQL là cách tốt hơn

Mở đầu. REST đã được nhiều developers sử dụng để gửi dữ liệu qua HTTP trong khi GraphQL thường được trình bày như một công nghệ thay thế các API REST.

0 0 99

- vừa được xem lúc

Quản lý và sử dụng API trong Nuxt bằng cách sử dụng Repository Pattern

Mở đầu năm mới, à nhầm, mở đầu bài viết. Cái tên NuxtJS chắc hẳn cũng không còn xa lạ gì với những bạn yêu thích VueJS nữa, đương nhiên mình cũng là một chàng trai dành tình yêu to lớn cho frameworks này.

0 0 226