>  기사  >  데이터 베이스  >  Redis 전류 제한을 구현하는 방법에는 몇 가지가 있습니까?

Redis 전류 제한을 구현하는 방법에는 몇 가지가 있습니까?

coldplay.xixi
coldplay.xixi원래의
2020-06-30 13:28:003300검색

redis 전류 제한을 구현하는 방법에는 다음 세 가지가 있습니다. 1. Redis의 setnx 작업을 기반으로 지정된 키에 대한 만료 방식을 설정합니다. 2. Redis 데이터 구조 zset을 기반으로 요청이 이루어집니다. zset array; 3. Redis의 토큰 버킷 알고리즘에 따라 출력 속도가 입력 속도보다 크면 흐름이 제한되어야 합니다.

Redis 전류 제한을 구현하는 방법에는 몇 가지가 있습니까?

Redis 전류 제한을 구현하는 방법에는 3가지가 있습니다. setnx 명령 CAS(비교 및 교체) 작업 중에 지정된 키에 대해 만료 관행(만료)이 설정됩니다. 전류 제한의 주요 목적은 내 코드 프로그램에 액세스하기 위한 요청이 N개 있는 것입니다. 따라서 setnx를 사용하면 이 기능을 쉽게 얻을 수 있습니다.

예를 들어, 10초 내에 20개의 요청을 제한해야 하는 경우 setnx를 설정할 때 만료 시간을 10으로 설정할 수 있습니다. 요청된 setnx 수가 20에 도달하면 현재 제한 효과가 달성됩니다. 코드는 비교적 간단하므로 표시하지 않습니다.

물론 이 접근 방식에는 많은 단점이 있습니다. 예를 들어 1~10초를 계산할 때 N초 내에 M개의 요청을 계산해야 한다면 N을 유지해야 합니다. Redis Key 및 기타 문제

관련 학습 권장 사항:

redis 비디오 튜토리얼

두 번째: Redis 기반 데이터 구조 zset

실제로 전류 제한과 관련된 가장 중요한 것은 슬라이딩 윈도우입니다. 위에서도 언급한 내용인데 어떻게 1-10이 2-11이 되었나요? 실제로 시작 값과 끝 값은 모두 각각 +1입니다.

그리고 Redis의 목록 데이터 구조를 사용하면 이 기능을 쉽게 구현할 수 있습니다.

요청을 zset 배열로 만들 수 있으며, 각 요청이 들어올 때 값은 고유하게 유지되며 UUID로 생성될 수 있습니다. 점수를 사용할 수 있습니다. 현재 타임스탬프 내의 요청 수를 계산하는 데 점수를 사용할 수 있기 때문에 현재 타임스탬프가 나타납니다. zset 데이터 구조는 2 타임스탬프 내의 요청 수를 쉽게 얻을 수 있도록 범위 메서드도 제공합니다

코드는 다음과 같습니다

public Response limitFlow(){
        Long currentTime = new Date().getTime();
        System.out.println(currentTime);
        if(redisTemplate.hasKey("limit")) {
            Integer count = redisTemplate.opsForZSet().rangeByScore("limit", currentTime -  intervalTime, currentTime).size();        // intervalTime是限流的时间 
            System.out.println(count);
            if (count != null && count > 5) {
                return Response.ok("每分钟最多只能访问5次");
            }
        }
        redisTemplate.opsForZSet().add("limit",UUID.randomUUID().toString(),currentTime);
        return Response.ok("访问成功");
    }

위 코드를 통해 슬라이딩 윈도우 효과를 얻을 수 있으며, N초마다 보장됩니다. 최대 M개의 요청에서는 zset의 데이터 구조가 점점 더 커지는 단점이 있습니다. 구현 방법은 비교적 간단합니다.

세 번째 유형: Redis 기반 토큰 버킷 알고리즘

전류 제한에 관해서라면 토큰 버킷 알고리즘을 언급해야 합니다. 토큰 버킷 알고리즘은 버킷 알고리즘이라고도 합니다. 자세한 내용은 Du Niang의 설명을 참조하세요. 토큰 버킷 알고리즘

토큰 버킷 알고리즘은 입력 비율보다 출력 비율이 높을 때 언급됩니다. 트래픽 제한이 초과되었습니다.

즉, 요청에 액세스할 때마다 Redis에서 토큰을 얻을 수 있다는 것은 한도를 초과하지 않았다는 의미이고, 얻을 수 없으면 결과는 반대가 된다는 의미입니다. .

위의 아이디어를 바탕으로 Redis의 List 데이터 구조를 결합하여 이러한 코드를 쉽게 구현할 수 있습니다.

목록의 leftPop을 사용하여 토큰을 얻습니다.

// 输出令牌
public Response limitFlow2(Long id){
        Object result = redisTemplate.opsForList().leftPop("limit_list");
        if(result == null){
            return Response.ok("当前令牌桶中无令牌");
        }
        return Response.ok(articleDescription2);
    }

그런 다음 Java의 예약된 작업을 사용하여 정기적으로 rightPush를 수행합니다. List 는 물론 토큰도 고유해야 하므로 여기서는 여전히 UUID를 사용하여 생성합니다.

// 10S的速率往令牌桶中添加UUID,只为保证唯一性
    @Scheduled(fixedDelay = 10_000,initialDelay = 0)
    public void setIntervalTimeTask(){
        redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());
    }

요약하자면, 현재 제한 방법의 경우 코드 구현을 시작하는 것이 어렵지 않습니다. 인터페이스의 흐름을 제한하고 궁극적으로 웹사이트를 보호하기 위해 AOP 또는 필터를 사용합니다.

Redis는 실제로 캐싱 및 분산 잠금 기능뿐만 아니라 다른 용도로도 많이 사용됩니다. 데이터 구조는 단순히 String, Hash, List, Set 및 Zset이 아닙니다. 관심 있는 사람들은 그의 GeoHash 알고리즘, BitMap, HLL 및 Bloom 필터 데이터(Redis 4.0 이후에 추가됨, Docker를 사용하여 redislabs/rebloom을 직접 설치할 수 있음) 구조에 대해 후속 조치를 취할 수 있습니다.

궁금한 점이 있으시면 메시지를 남겨주세요

위 내용은 Redis 전류 제한을 구현하는 방법에는 몇 가지가 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.