使用Redis作為簡單的限流計數器幾種實現策略

2022-03-06 06:53:43 字數 1229 閱讀 6206

在實現簡單的介面限流或者商品秒殺時,一般需要redis來作為計數器。但是在併發場景下,使用不當的可能會踩坑。

這裡主要的坑就是:使用不當,會造成key永久有效,永不過期,導致value一直在increment,無法起到限流的作用。

下面就以反面例子說明:

本文使用的是spring-data-redis的redistemplate

org.springframework.boot

spring-boot-starter-data-redis

反面例項

1

public

void limit() throws

exception

7if (incrresult > 100)

10 }

這個**的錯誤在第4,5行。

因為redisservice.increment()在key為空的情況下,不是原子性操作。

實際是兩步操作,首先redis 的incr 命令將 key 中儲存的數字值增1;如果 key 不存在,那麼 key 的值會先被初始化為 0 ,然後再執行 incr 操作,且將key的有效時間設定為長期有效。

當計數器設定成功之後,給key加expire時間時出現服務故障,將會導致整個key一直存在。無法起到限流作用

正確寫法1

1

public

void limit() throws

exception 8//

防止出現併發操作未設定超時時間的場景,這樣key就是永不過期,存在風險

9if (redisservice.getexpire(rediskey, timeunit.seconds) == -1)

13if (incrresult > 100)

16 } catch

(exception e)

20 }

正確寫法2:給key加乙個時間字尾,這樣即時出現永不過期的key也只影響其中某一時間段內的key

1

public

void limit() throws

exception

8if (incrresult > 100)

11 } catch

(exception e)

15 }

Redis 簡單限流

首先我們來看乙個常見 的簡單的限流策略。系統要限定使用者的某個行為在指定的時間裡只能允許發生 n 次,如何使用 redis 的資料結構來實現這個限流的功能?這個限流需求中存在乙個滑動時間視窗,想想 zset 資料結構的 score 值,是不是可以通過 score 來圈出這個時間視窗來。而且我們只需要...

redis簡單限流

需求 如果要保證乙個使用者一分鐘內只能訪問5次介面,超過就拒絕範圍。這個限流需求中存在乙個滑動時間視窗,想想 zset 資料結構的 score 值,是不是可以通過 score 來圈出這個時間視窗來。而且我們只需要保留這個時間視窗,視窗之外的資料都可以砍掉。那這個 zset 的 value 填什麼比較...

使用Redis進行限流

通過使用註解 提供介面形式與引數形式2種方式 針對性的對介面進行限流,底層使用redis配合lua指令碼實現令牌桶。public class redisratelimiter public boolean tryacquire string flag,int maxpermits,int addra...