Redis接口訪問優(yōu)化的方法步驟
說明:之前寫過一篇使用Redis接口訪問的博客,如下。最近有相關(guān)需求,把代碼拿出來后,做了一些優(yōu)化,挺有意思的,本文介紹在原基礎(chǔ)上
優(yōu)化
總的來說,這次使用Redis實現(xiàn)接口防抖,增加了一個時間段參數(shù),可以限制接口在某個時間段內(nèi),訪問不能超過多少次。如下:
(自定義注解,打在接口上)
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 自定義注解 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface LimitAccess { /** * 限制訪問的key * @return */ String key(); /** * 限制訪問次數(shù) * @return */ int times(); /** * 時間段 * @return */ int duration(); }
(切面,實現(xiàn)限制訪問)
import com.hezy.annotation.LimitAccess; import lombok.extern.log4j.Log4j2; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; /** * AOP類(通知類) */ @Component @Aspect @Log4j2 public class LimitAspect { @Value("${access.enable:false}") private boolean enable; @Autowired private RedisTemplate redisTemplate; @Pointcut("@annotation(com.hezy.annotation.LimitAccess)") public void pt(){}; @Around("pt()") public Object aopAround(ProceedingJoinPoint pjp) throws Throwable { // 設(shè)置一個開關(guān),控制是否執(zhí)行 if (!enable) { return pjp.proceed(); } // 獲取切入點上面的自定義注解 Signature signature = pjp.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; // 獲取方法上面的注解 LimitAccess limitAccess = methodSignature.getMethod().getAnnotation(LimitAccess.class); // 獲取注解上面的屬性值 int limit = limitAccess.times(); String key = limitAccess.key(); int duration = limitAccess.duration(); // 遞增鍵的值,如果鍵不存在則初始化為1 Long currentCount = redisTemplate.opsForValue().increment(key, 1); // 如果鍵是新創(chuàng)建的,設(shè)置過期時間 if (currentCount != null && currentCount == 1) { redisTemplate.expire(key, duration, TimeUnit.SECONDS); } // 檢查是否超過限制 if (currentCount != null && currentCount > limit) { log.info("訪問過于頻繁: " + pjp.toLongString()); throw new RuntimeException("訪問過于頻繁"); } return pjp.proceed(); } }
(使用,在對應(yīng)的接口上,打上注解,填上數(shù)值,如下表示,1秒內(nèi)不能訪問超過3次)
@LimitAccess(key = "test", times = 3, duration = 1) @GetMapping public String test() { return demoService.test(); }
另外,在代碼中加了一個開關(guān),可在配置文件中設(shè)置此配置,表示開啟或者關(guān)閉,默認(rèn)是關(guān)閉的
access: enable: true
啟動項目,測試一下
思考
以上代碼,有兩點需要思考:
注解能不能加在Service層的方法上,加了有沒有用?另外加了會不會讓聲明式事務(wù)失效?
這個限制,沒有到用戶的維度,也就是說所有的用戶,只要在一個時間段內(nèi)訪問超過次數(shù)就限制,這顯然是不行的。有什么辦法嗎?
第一點,我測試過,注解可以加在Service層方法上,是可以的,不會讓事務(wù)失效,如下:
@LimitAccess(key = "deleteUserById", times = 3, duration = 1) @Transactional @Override public void deleteUserById(Integer id) { // 刪除用戶 userMapper.deleteUserById(id); int i = 1 / 0; // 刪除用戶對應(yīng)的角色 userMapper.deleteUserRoleMapper(id); }
接口限制,事務(wù),都生效了。
第二點,這確實是個問題,要做到針對用戶層面的接口限制是必須的,不然有一個用戶惡意刷新,其他用戶都用不了了,這怎么可以。要解決這個問題,首先要拿到當(dāng)前操作用的標(biāo)識,用戶名、用戶ID,然后再存入key的時候,拼接上這個標(biāo)識作為key。
String key = limitAccess.key() + 用戶標(biāo)識(用戶名、用戶id);
獲取當(dāng)前用戶信息,參考下面這篇文章:
如果你不是自己從0開發(fā)項目,一般成熟的項目都會有獲取當(dāng)前操作用戶信息的方式的。實在不行,你讓前端把用戶id作為參數(shù)傳給你,你在切面里獲取這個用戶id都可以。
總結(jié)
本文是對之前用Redis接口訪問的優(yōu)化,以及對兩個問題的考慮,希望能對大家有啟發(fā)。
獲取源碼:https://github.com/HeZhongYing/limit_access_demo
到此這篇關(guān)于Redis接口訪問優(yōu)化的方法步驟的文章就介紹到這了,更多相關(guān)Redis接口訪問優(yōu)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis+自定義注解+AOP實現(xiàn)聲明式注解緩存查詢的示例
實際項目中,會遇到很多查詢數(shù)據(jù)的場景,這些數(shù)據(jù)更新頻率也不是很高,一般我們在業(yè)務(wù)處理時,會對這些數(shù)據(jù)進行緩存,本文主要介紹了Redis+自定義注解+AOP實現(xiàn)聲明式注解緩存查詢的示例,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04RedisTemplate 實現(xiàn)基于Value 操作的簡易鎖機制(示例代碼)
本文將介紹如何使用 RedisTemplate 的 opsForValue().setIfAbsent() 方法來實現(xiàn)一種簡單的鎖機制,并提供一個示例代碼,展示如何在 Java 應(yīng)用中利用這一機制來保護共享資源的訪問,感興趣的朋友跟隨小編一起看看吧2024-05-05Redis TTL命令實現(xiàn)數(shù)據(jù)生存時間
生存時間可以通過Redis中的不同命令來設(shè)置、查看和管理,TTL命令是其中之一,本文主要介紹了Redis TTL命令實現(xiàn)數(shù)據(jù)生存時間,具有一定的參考價值,感興趣的可以了解一下2024-06-06