Giải pháp cho rate limit api

hi mn, hiện tại e có 1 web khi KH mua sẽ call đến 1 api. bình thường thì đang hoạt động tốt, nhưng khi e thử test request liên tục đến api đó thì có vấn đề.
ví dụ số dư KH còn 100K, mua 1 đơn hết 50k. nếu mua chậm thì sẽ được 2 đơn là sẽ thông báo số dư không đủ. nhưng khi e viết thử 1 file php curl request liên tục đến api đó thì mua được tới 5 6 đơn (kiểu như là request lần đầu nó chưa xử lý xong, số dư vẫn còn nguyên, request tiếp vẫn mua được ý).

code thì em dựa vào api key của KH để lấy số dư ban đầu - giá trị đơn = số dư cuối.
em tính làm cái rate limit, nhưng chưa biết để thế nào cho hợp lí, vì cao điểm có khách mua vài giây 1 đơn rồi ý ah. ( ví dụ KH mua 2s 1 đơn, nhưng api của e mất khoảng 3s để xử lý xong thì sẽ bị gặp vấn đề trên )

Ủa? Đây đâu phải vấn đề dùng rate limiter để giải quyết đâu cậu?
Vấn để này cậu có thể dùng optimistic lock để giải quyết đó :smile: Thử nghiên cứu nhé cậu!

5 Likes

rate limiter dùng để chống spam mà nhỉ?

3 Likes

thank mn nha. để e tìm hiểu :smiley:

optimistic lock là xử lý về phía DB chứ ko phải code phải ko ak

chào bạn, đoạn này mình ko hiểu bạn đang nói gì
mua chậm ở đây là ntn Bạn?

tức là kiểu vào lúc 1h họ order 1 đơn, 1h30p họ order 1 đơn á thì ok. còn mình muốn test trường hợp dùng code để curl mua liên tục 1s 1 đơn thì bị vấn đề như mình nói á

1 Like

Vấn đề của cậu là cậu cần synchronized giữa các process thực hiện cập nhật database, để đảm bảo shopper không mua nhiều hơn số tiền họ có.
Nếu 1 shopper có 100 dollar, và họ đồng thời mua 2 item 90 dollar tại một thời điểm, họ có thể mua được 2 items đó khi cậu không đồng bộ được 2 process. Vì số tiền họ có được lưu ở database, nên hẳn nhiên cậu cần lock ở database rồi :smile:
Tất nhiên là cậu có thể cực đoan dùng rate limiter để bắt người dùng được phép mua 1 đơn hàng trong vài s (cậu hoàn toàn có thể tự implement 1 rate limiter đơn giản cho việc này dùng giải thuật bucket leak). Cơ mà, nó cực đoan, vì tự dưng shopper phải chờ vài s mới có thể mua đồ tiếp => trải nghiệm vô cùng tồi tệ.

Optimistic lock sẽ giúp cậu không giảm throughput của database và hệ thống của cậu, nếu cậu implement đúng. Trong kịch bản ở ví dụ trên, cậu sẽ dễ dàng accept 1 request, và reject 1 request vì version thay đổi. Người dùng có thể retry lại một lần nữa và fail vì hết tiền.
Cậu cũng có thể lock entry ở database, để đảm bảo chỉ có 1 process được update entry tại 1 thời điểm. Cơ mà nó sẽ giảm throughput database của cậu tại entry đó, và cậu cũng cần lựa chọn database engine phù hợp để làm điểu đó.
Cân nhắc nhé!

6 Likes

rate limiter sử dụng trong trường hợp này nhe: Hướng dẫn bảo mật API chống lộ Endpoint (chủ yếu rate limiter để xử lý HTTP request chứ không xử lý database)

3 Likes

em đang dùng mysql và có tìm thử thấy https://riptutorial.com/mysql/example/24166/row-level-locking, nó có syntax SELECT … FOR UPDATE nó sẽ tự lock , dùng như này đc ko ạ

Đúng rồi đó cậu. Đó là cách cậu lock record (row lock) đó :smile:
Cậu cũng nên check xem bảng đó dùng database engine nào. Nếu là innoDB (default) thì tốt, nếu không thì cậu phải cẩn thận (Chẳng hạn, MyISAM chỉ có table lock mà không có row lock).

Hope it helps!

3 Likes

trường hợp mình ko muốn show lỗi trong khi process 1 đang update (đang bị lock) thì try catch kèm while true, rồi chờ đến khi nó xử lý xong là nó unlock rồi xử lý tiếp process 2 ạ

Không cậu ơi @@
Khi row đó bị lock, connection của các process khác sẽ bị hang ở cả 2 phía database và application để chờ nhả lock, cho tới khi một trong 2 bên timeout (cậu có thể set timeout cho cả 2 phía, nhưng thường mọi người sử dụng timeout default phía DB và set timeout hợp lý phía application). Database sẽ lần lượt xử lý cho từng request ở từng connection một.

Khi timeout xảy ra, cậu nên nhận được exception. Cậu có thể làm gì đó tùy ý với exception đó.
Vậy nên, không có while true gì cả :smile:

6 Likes

à tức là trong khi nó đang lock mà có 1 process update mới thì nó chờ process trước đó xong chứ không phải là nó sẽ throw ra exception ạ

1 Like

Cậu hiểu đúng rồi đó :smile:

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?