redisson滑動時間窗應(yīng)用場景解決方案
更新時間:2024年01月08日 09:58:52 作者:StrangerIt
前10分鐘內(nèi)累計3次驗證失敗后,增加圖形驗證碼驗證條件,前10分鐘內(nèi)累計6次驗證失敗后,系統(tǒng)自動鎖定該賬號15分鐘,15分鐘后自動解鎖,本文給大家分享redisson滑動時間窗應(yīng)用場景解決方案,感興趣的朋友一起看看吧
概述
前10分鐘內(nèi)累計3次驗證失敗后,增加圖形驗證碼驗證條件,前10分鐘內(nèi)累計6次驗證失敗后,系統(tǒng)自動鎖定該賬號15分鐘,15分鐘后自動解鎖;
方案
基于redisson(zset)滑動時間窗記錄最近10分鐘內(nèi)該賬戶登錄失敗次數(shù)
統(tǒng)計次數(shù)、每次失敗加1
/**
* 統(tǒng)計請求次數(shù)
*
* @param windowTime 窗口時間,單位:秒
* @param key 登錄賬戶
* @return 請求次數(shù)
*/
public Integer count(int windowTime, String key) {
// 窗口結(jié)束時間
long windowEndTime = System.currentTimeMillis();
// 窗口開始時間
long windowStartTime = windowEndTime - windowTime * 1000L;
try {
// 創(chuàng)建 RBatch 實例,批量執(zhí)行命令
RBatch batch = redissonClient.createBatch();
// 添加元素 score=當(dāng)前時間戳 value=請求序列號,唯一不可重復(fù)
batch.getScoredSortedSet(key).addAsync(windowEndTime, UUID.randomUUID().toString());
// 統(tǒng)計數(shù)據(jù)
batch.getScoredSortedSet(key).countAsync(windowStartTime, true, windowEndTime, true);
// 清除窗口過期成員
batch.getScoredSortedSet(key).removeRangeByScoreAsync(0, true, windowStartTime, false);
// 設(shè)置key過期時間
batch.getScoredSortedSet(key).expireAsync(Duration.ofSeconds(windowTime));
// 執(zhí)行管道命令
BatchResult<?> batchResult = batch.execute();
// 返回統(tǒng)計數(shù)量
List<?> responses = batchResult.getResponses();
Integer number = (Integer) responses.get(1);
return number;
} catch (Exception e) {
log.error("統(tǒng)計請求次數(shù)異常!", e);
return null;
}
}獲取登錄失敗次數(shù)
/**
* 獲取對應(yīng)窗口的次數(shù)
* @param windowTime 窗口大小十分鐘,600s
* @param key
* @return
*/
public Integer getLastCachedCount(int windowTime, String key) {
// 窗口結(jié)束時間
long windowEndTime = System.currentTimeMillis();
// 窗口開始時間
long windowStartTime = windowEndTime - windowTime * 1000L;
try {
// 創(chuàng)建 RBatch 實例,批量執(zhí)行命令
RBatch batch = redissonClient.createBatch();
// 統(tǒng)計數(shù)據(jù),獲取上一次緩存存取的數(shù)據(jù)
RFuture<Integer> countFuture = batch.getScoredSortedSet(key).countAsync(windowStartTime, true, windowEndTime, true);
// 執(zhí)行管道命令
batch.execute();
// 等待統(tǒng)計數(shù)據(jù)完成并獲取結(jié)果
Integer count = countFuture.get();
// 如果結(jié)果為null,則返回0,否則返回計數(shù)值
return count == null ? 0 : count.intValue();
} catch (Exception e) {
log.error("獲取上一次緩存存取數(shù)據(jù)異常!", e);
// 如果出現(xiàn)異常,返回null
return null;
}
}清除登錄失敗次數(shù)
public void clearCachedCount(int windowTime, String key) {
// 窗口結(jié)束時間
long windowEndTime = System.currentTimeMillis();
// 窗口開始時間
long windowStartTime = windowEndTime - windowTime * 1000L;
try {
// 創(chuàng)建 RBatch 實例,批量執(zhí)行命令
RBatch batch = redissonClient.createBatch();
// 統(tǒng)計數(shù)據(jù),獲取上一次緩存存取的數(shù)據(jù)
batch.getScoredSortedSet(key).removeRangeByScoreAsync(windowStartTime, true, windowEndTime, true);
// 執(zhí)行管道命令
batch.execute();
// 如果結(jié)果為null,則返回0,否則返回計數(shù)值
} catch (Exception e) {
log.error("清楚登錄失敗記錄次數(shù)異常", e);
}
}到此這篇關(guān)于redisson滑動時間窗應(yīng)用場景的文章就介紹到這了,更多相關(guān)redisson滑動時間窗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何在SpringBoot中使用Redis實現(xiàn)分布式鎖
這篇文章主要介紹了如何在SpringBoot中使用Redis實現(xiàn)分布式鎖,在實際開發(fā)中有可能會遇到多個線程同時訪問同一個共享變量,那么上鎖就很重要了,需要的朋友可以參考下2023-03-03

