Redis가 흐름을 제한하는 세 가지 방식을 상세히 설명합니다.

점점 더 많은 병발 장면에 직면하면 흐름을 제한하는 것이 특히 중요하다.
물론 흐름 제한은 여러 가지 실현 방식이 있는데 Redis는 매우 강한 기능을 가진다. 나는 Redis로 세 가지 실현 방식을 실천했는데 비교적 간단하게 그 방식을 실현할 수 있다.Redis는 흐름을 제한할 수 있을 뿐만 아니라 데이터 통계, 부근의 사람 등 기능도 할 수 있는데 이것들은 나중에 다시 쓸 수 있다.

첫 번째: Redis 기반 setnx 작업


우리가 Redis의 분포식 자물쇠를 사용할 때 모두들 알다시피 setnx의 지령에 의존하여 CAS(Compare and swap)를 조작할 때 지정한 키에 기한이 지난 실천(expire)을 설정했다. 우리가 흐름을 제한하는 주요 목적은 단위 시간 내에 N 수량의 요청만 있으면 나의 코드 프로그램에 접근할 수 있도록 하는 것이다.그래서 setnx에 의존하면 이 방면의 기능을 쉽게 할 수 있다.
예를 들어 우리는 10초 안에 20개의 요청을 한정해야 한다. 그러면 우리는 setnx에 만료 시간 10을 설정할 수 있다. 요청한 setnx의 수량이 20에 이르면 제한 효과에 도달한다.코드가 비교적 간단해서 전시를 하지 않겠다.
구체적인 setnx 용법은 나의 다른 블로그를 참조할 수 있다RedisTemplate에서 Redis 분산 자물쇠로 인한 일련의 문제
물론 이런 방법의 폐단은 매우 많다. 예를 들어 1-10초를 통계할 때 2-11초 안에 통계할 수 없다. 만약에 N초 안에 M개의 요청을 통계해야 한다면 우리의 Redis에서 N개의 키를 유지해야 하는 등 문제가 있다.

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


사실 흐름 제한과 관련된 가장 주요한 것은 슬라이딩 창이다. 위에서도 1-10이 어떻게 2-11이 되는지 언급했다.즉, 시작 값과 끝 값이 각각 +1이면 됩니다.
저희가 만약에 Redis의list 데이터 구조를 사용하면 이 기능을 쉽게 실현할 수 있습니다.
우리는 요청을 zset 수조로 만들 수 있습니다. 요청이 들어올 때마다value는 유일하고 UUID로 생성할 수 있으며, score는 현재 시간 스탬프로 표시할 수 있습니다. 왜냐하면 score는 현재 시간 스탬프 안에 얼마나 많은 요청 수량이 있는지 계산할 수 있기 때문입니다.zset 데이터 구조도range 방법을 제공하여 우리는 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초 안에 여러 개의 요청을 보장할 수 있으며 단점은 zset의 데이터 구조가 점점 커진다는 것이다.실현 방식도 상대적으로 비교적 간단하다.

세 번째: Redis 기반 영패통 알고리즘


흐름 제한을 언급하면 어쩔 수 없이 영패통 알고리즘을 언급해야 한다.구체적으로 도모의 해석을 참조할 수 있다토큰통 알고리즘
영패통 알고리즘은 입력 속도와 출력 속도를 언급했는데 출력 속도가 입력 속도보다 크면 유량 제한을 초과하는 것이다.
즉, 우리가 요청을 방문할 때마다 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);
    }
그리고 자바의 타이밍 퀘스트에 의존하여 List에서 rightPush 영패를 타이밍합니다. 물론 영패도 유일성이 필요하기 때문에 저는 UUID로 생성했습니다.

// 10S UUID, 
    @Scheduled(fixedDelay = 10_000,initialDelay = 0)
    public void setIntervalTimeTask(){
        redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());
    }
종합적으로 코드 구현의 시작은 어렵지 않다. 이러한 흐름 제한 방식에 대해 우리는 AOP나 Filter에 상기 코드를 추가하여 인터페이스의 흐름을 제한하고 최종적으로 당신의 사이트를 보호할 수 있다.
Redis는 사실 다른 용도가 많다. 그의 역할은 캐시, 분포식 자물쇠의 역할만이 아니다.그의 데이터 구조도 String,Hash,List,Set,Zset만 있는 것이 아니다.흥미로운 것은 그의 GeoHash 알고리즘을 후속적으로 이해할 수 있다.BitMap, HLL 및 블론 필터 데이터(Redis4.0 이후 추가, Docker로 Redislabs/rebloom) 구조를 직접 설치할 수 있습니다.현재 나도 이러한 Redis의 다른 작용을 모두 나의 블로그 사이트에 사용했다.
Redis의 흐름 제한을 실현하는 세 가지 방식에 대한 상세한 설명을 드리겠습니다. 더 많은 Redis 흐름 제한 내용은 저희 이전의 글을 검색하거나 아래의 관련 글을 계속 훑어보시기 바랍니다. 앞으로 많은 응원 부탁드립니다!

좋은 웹페이지 즐겨찾기