루아 스크립트를 제한 :
로컬 key_local redis.call = ( ' setnx ' , KEYS [ 1 ], 0 ) 의 경우 tonumber (key_local) == 0 다음 경우 tonumber (redis.call ( ' 얻을 ' , KEYS [ 1 ]))> = tonumber (ARGV [ 2 ]) 후 복귀 거짓 다른 redis.call ( ' 증분을 ' 키 [ 1 ]) 반환 진정한 단부 다른 redis.call ( ' 증분을 '키들 [ 1 ]) redis.call ( ' pexpire ' , KEYS는 [ 1 ] ARGV는 [ 1 ]) 반환 진정한 단부
자바 호출 코드 :
수입 org.springframework.beans.factory.annotation.Autowired; 수입 org.springframework.core.io.ClassPathResource; 수입 org.springframework.data.redis.core.StringRedisTemplate; 수입 org.springframework.data.redis.core.script.DefaultRedisScript; 수입 org.springframework.scripting.support.ResourceScriptSource; 수입 org.springframework.stereotype.Component; 수입 Collections의; @Component 공공 클래스 GlobalLimitComponent { @Autowired 개인 StringRedisTemplate redisTemplate; / ** *针对某个키使用의 루아脚本进行限流 * 사용 루아 장점은, 복수의 커맨드가 라인에 전달되도록하고 레디 스 서버가 일련의 실행 순서가 동시성 문제를 방지하기위한 추가 명령을 삽입 할 수 있도록, 순차적으로 행해진 다 * 단계 : * 1 키가 있는지 판단 그렇지 않으면, 여러 개의 (m)까지 대 (n)에 얼마나 많은 밀리 설정 키 저장하는 설정 값 의 값이 존재하는 경우 * 2는, 타임 아웃이 삭제 된 경우, 및 단계 1 재실행 제 키 초과 여부를 판정한다 키가 타임 아웃되지 않은 경우, 이는 m은 n 배 밀리 초에 최대 한계를 초과 하는지를 판정 * * @param의 키 * / 공용 부울 getGlobalLimitByLua (문자열 키 INT mlitimes, INT MAXCOUNT) { DefaultRedisScript <불> = redisScript 새로운 새 DefaultRedisScript <> () ; redisScript.setScriptSource ( 새로운 새 ResourceScriptSource ( 새로운 새 ClassPathResource가 ( "/ limit.lua" ))); redisScript.setResultType (. 부울 클래스 ); 반환 redisTemplate.execute (redisScript, Collections.singletonList (키) 한 String.valueOf (mlitimes) 한 String.valueOf (MAXCOUNT)); } }
최적화 포인트 : 루아 스크립트는 항상 각 통화의 해시 값이 실행되는 서버 레디 스에 업로드 할 수 해시 값을 얻기 위해 업로드하지 않는다;