分布式限流

一、分布式限流实现秒杀

在高并发场景下,流量很大的时候需要进行限流操作,否则可能会出现系统崩溃或者对相关业务造成影响。秒杀场景是一个典型的高并发场景。很多网站都会在一定时间内提供限量商品,用户抢购时都是在同一时间内进行,此时需要限制每个用户的请求次数,否则会出现恶意刷单等现象。而分布式限流可以使我们更加高效地解决这个问题。

下面是一个实现秒杀的分布式限流代码示例:

public boolean tryAcquireSeckill() {
    // 每秒放行5次请求
    RateLimiter rateLimiter = RateLimiter.create(5);
    return rateLimiter.tryAcquire();
}

二、分布式限流三种算法

分布式限流主要包括计数器算法、令牌桶算法和漏桶算法。

计数器算法是指通过统计一段时间内的请求次数,当超过一定的阈值时就进行限流操作。

public class CountAlgorithm {
    private static AtomicInteger count = new AtomicInteger(0);

    public static boolean tryAcquire() {
        int newCount = count.incrementAndGet();
        if(newCount > 10) {
            return false;
        } else {
            return true;
        }
    }
}

令牌桶算法则是需要令牌才能进行访问的一种算法。可以设置每秒钟发放多少个令牌,每发放一个令牌后就会扣除一个。当桶内令牌数不足时,无法进行访问。

public class TokenBucketAlgorithm {
    private static RateLimiter rateLimiter = RateLimiter.create(10);

    public static boolean tryAcquire() {
        return rateLimiter.tryAcquire();
    }
}

漏桶算法则是保证一定的流量输出,防止流量被突发的请求消耗。

public class LeakyBucketAlgorithm {
    // 桶容量
    private static int capacity = 10;
    // 水流速度
    private static int rate = 1;
    // 时间间隔
    private static int timeInterval = 1000;
    // 当前水量
    private static int water = 0;
    // 上次漏水的时间
    private static long lastTime = System.currentTimeMillis();

    public static synchronized boolean tryAcquire() {
        // 计算流入的水量
        long now = System.currentTimeMillis();
        water = Math.max(0, water - (int)((now - lastTime) / timeInterval) * rate);
        lastTime = now;
        if(water < capacity) {
            water++;
            return true;
        } else {
            return false;
        }
    }
}

三、分布式限流器

分布式限流器是一种通用的限流框架,可以在各种业务场景下使用。使用该框架可以有效控制流量,防止系统崩溃。

下面是一个基于Google Guava库实现的分布式限流器:

public class RateLimiterDecorator {

    private static final String SEPARATOR = "_";

    private int permitsPerSecond;

    private LoadingCache loadingCache;

    private Function keyMapper;

    public RateLimiterDecorator(int permitsPerSecond, Function keyMapper) {
        this.permitsPerSecond = permitsPerSecond;
        this.keyMapper = keyMapper;
        CacheLoader loader = new CacheLoader() {
            @Override
            public RateLimiter load(String key) throws Exception {
                return RateLimiter.create(permitsPerSecond);
            }
        };
        loadingCache = CacheBuilder.newBuilder().build(loader);
    }

    public boolean tryAcquire(T key) {
        try {
            return loadingCache.get(keyMapper.apply(key)).tryAcquire();
        } catch (ExecutionException e) {
            e.printStackTrace();
            return false;
        }
    }
}

四、分布式限流框架

分布式限流框架是一种将限流逻辑封装在框架中,可以通过配置参数实现对流量的限制,从而防止系统崩溃,同时可以有效提高程序的可维护性。

下面是一个基于Spring Cloud Gateway和Redis实现的分布式限流框架:

public class RateLimiterFilter implements GlobalFilter, Ordered {

    private static final String REQUEST_PATH_KEY = "request_path";
    private static final String REQUEST_METHOD_KEY = "request_method";
    private static final String ALLOW_PATH_PATTERN_KEY = "allow_path_pattern";
    private static final String RATE_LIMIT_KEY = "rate_limit";
    private static final String REDIS_RATE_LIMIT_KEY_PREFIX = "rate-limit:";

    private StringRedisTemplate redisTemplate;
    private PathMatcher pathMatcher = new AntPathMatcher();

    public RateLimiterFilter(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String requestMethod = exchange.getRequest().getMethodValue();
        String requestPath = exchange.getRequest().getPath().value();
        // 遍历配置文件中的限流规则
        redisTemplate.opsForHash().entries(RATE_LIMIT_KEY).entrySet().stream()
                .filter(entry -> {
                    String allowPathPattern = (String)entry.getValue();
                    return pathMatcher.match(allowPathPattern, requestPath);
                })
                .forEach(entry -> {
                    String redisKey = REDIS_RATE_LIMIT_KEY_PREFIX + entry.getKey() + ":" + requestMethod;
                    long count = redisTemplate.opsForValue().increment(redisKey, 1);
                    if(count == 1) {
                        redisTemplate.expire(redisKey, 60, TimeUnit.SECONDS);
                    }
                    long threshold = Long.parseLong((String)entry.getValue());
                    if(count > threshold) {
                        exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
                        return exchange.getResponse().setComplete();
                    }
                });
        exchange.getAttributes().put(REQUEST_PATH_KEY, requestPath);
        exchange.getAttributes().put(REQUEST_METHOD_KEY, requestMethod);
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1000;
    }
}

五、分布式限流方案

针对不同的系统架构和业务场景,可以选择不同的分布式限流方案。比如基于Redis的分布式限流、基于Zookeeper的分布式限流等。下面是一个基于Redis的分布式限流代码示例:

public class RedisRateLimiter {

    private static final String REDIS_RATE_LIMIT_KEY_PREFIX = "rate-limit:";
    private StringRedisTemplate redisTemplate;

    public RedisRateLimiter(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public boolean tryAcquire(String key, int permits, int seconds) {
        String redisKey = REDIS_RATE_LIMIT_KEY_PREFIX + key;
        long count = redisTemplate.opsForValue().increment(redisKey, 1);
        if(count == 1) {
            redisTemplate.expire(redisKey, seconds, TimeUnit.SECONDS);
        }
        long threshold = permits;
        if(count > threshold) {
            return false;
        } else {
            return true;
        }
    }
}

六、分布式限流组件

随着分布式限流的应用日益广泛,市面上也出现了一些比较成熟的分布式限流组件,如Sentinel、Zookeeper。这些组件具有使用方便、稳定性高的特点,可以为我们提供基础限流组件,加快开发效率。

下面是一个基于Sentinel的分布式限流代码示例:

public class SentinelRateLimiter {

    private static final String RESOURCE_NAME = "resource_name";
    private static final String FLOW_CONTROLLER = "flow_controller";
    private static final String THRESHOLD_TYPE = "grade";

    public boolean tryAcquire(String resourceId, double permits) {
        Entry entry = null;
        try {
            entry = SphU.entry(resourceId, ResourceType.COMMON, EntryType.IN);
            if(entry != null) {
                // do something
                return true;
            }
        } catch (BlockException e) {
            // handle exception
        } finally {
            if(entry != null) {
                entry.exit();
            }
        }
        return false;
    }

    public static void initFlowRule(double threshold) {
        List rules = new ArrayList();
        FlowRule rule = new FlowRule();
        rule.setClusterMode(false);
        rule.setCount(threshold);
        rule.setResource(RESOURCE_NAME);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setLimitApp(RuleConstant.LIMIT_APP_DEFAULT);
        rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
        rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        rule.setWarmUpPeriodSec(10);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }

    public static void registerFlowController(double threshold) {
        String type = THRESHOLD_TYPE;
        AbstractRule rule = null;
        switch(type) {
            case RuleConstant.FLOW_GRADE_QPS:
                rule = new FlowRule(RESOURCE_NAME)
                        .setCount(threshold)
                        .setGrade(RuleConstant.FLOW_GRADE_QPS);
                break;
            case RuleConstant.FLOW_GRADE_THREAD:
                rule = new DegradeRule(RESOURCE_NAME)
                        .setCount(threshold)
                        .setGrade(RuleConstant.FLOW_GRADE_THREAD);
                break;
            case RuleConstant.FLOW_GRADE_EXCEPTION_RATIO:
                rule = new DegradeRule(RESOURCE_NAME)
                        .setCount(threshold)
                        .setGrade(RuleConstant.FLOW_GRADE_EXCEPTION_RATIO);
                break;
            default:
                break;
        }
        if(rule != null) {
            FlowRuleManager.register2Property(rule.property());
            FLOW_CONTROLLER = type;
        }
    }
}

七、阿里哨兵分布式限流原理

阿里哨兵是一个针对分布式系统的流量控制组件,它通过不同的限流策略进行流量控制,从而防止流量被突发的请求消耗。

下面是阿里哨兵的分布式限流原理:

首先,哨兵会将应用程序的不同资源进行抽象,并且对每个资源设置不同的阈值。然后,每个应用程序都需要从阿里云哨兵服务中获取相关资源的限流规则,当应用程序达到限流规则的阈值时哨兵就会进行限流控制。哨兵还可以通过实时监控和动态感知应用程序资源的变化,从而实现动态调整限流策略的功能。

八、分布式潮流控制器

分布式潮流控制是指在网络系统中对电力负荷进行控制,从而保障电网的正常运行。分布式潮流控制器可以通过协调不同的电力负荷,使得电网的总负荷保持在一个正常的范围内,从而避免电网出现过载状态。

下面是一个分布式潮流控制器的代码示例:

public class DistributedPowerFlowController {

private static final String LOAD_NODE = "load";
private static final String GENERATOR_NODE = "generator";
private static final String TRANSFORMER_NODE = "transformer";

private static double[] load = {100, 100, 100};
private static double[] generator = {200, 200, 200};
private static double[] transformer = {300, 300, 300};

private static final double[][] Y = {
{1, -1, 0},
{0, 1, -1},
{-1, 0, 1}
};

public static double[] getFlow() {

// 构造潮流控制方程
double[][] A = new double[3][3];
double[] b = new double[3];
for(int i=0; i<Y.length; i++) {
for(int j=0; j<Y[i].length; j++) {
if(i == j)

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/245866.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 13:11
下一篇 2024-12-12 13:11

相关推荐

  • KeyDB Java:完美的分布式高速缓存方案

    本文将从以下几个方面对KeyDB Java进行详细阐述:KeyDB Java的特点、安装和配置、使用示例、性能测试。 一、KeyDB Java的特点 KeyDB Java是KeyD…

    编程 2025-04-29
  • Java Hmily分布式事务解决方案

    分布式系统是现在互联网公司架构中的必备项,但随着业务的不断扩展,分布式事务的问题也日益凸显。为了解决分布式事务问题,Java Hmily分布式事务解决方案应运而生。本文将对Java…

    编程 2025-04-28
  • JL Transaction – 实现分布式事务管理的利器

    本文将为大家介绍JL Transaction,这是一款可以实现分布式事务管理的开源事务框架,它可以帮助企业在分布式环境下有效地解决事务的一致性问题,从而保障系统的稳定性和可靠性。 …

    编程 2025-04-28
  • 使用RPC研发云实现分布式服务交互

    本文将基于RPC研发云,阐述分布式服务交互实现的过程和实现方式。 一、RPC研发云简介 RPC研发云是一种基于分布式架构的服务框架,在处理不同语言之间的通信上变得越来越流行。通过使…

    编程 2025-04-28
  • 分布式文件系统数据分布算法

    数据分布算法是分布式文件系统中的重要技术之一,它能够实现将文件分散存储于各个节点上,提高系统的可靠性和性能。在这篇文章中,我们将从多个方面对分布式文件系统数据分布算法进行详细的阐述…

    编程 2025-04-27
  • 使用Spring Cloud Redis实现分布式缓存管理

    一、背景介绍 在分布式互联网应用中,缓存技术扮演着非常重要的角色。缓存技术能够有效减轻数据库的访问压力,提高应用的访问速度。在分布式应用中,如何统一管理分布式缓存成为了一项挑战。本…

    编程 2025-04-24
  • 使用Kubernetes(K8s)搭建分布式系统

    一、Kubernetes概述 Kubernetes是一个用于自动部署、扩展和管理容器化应用程序的开源平台。其提供了高可用性、自我修复能力和易于扩展的特征,使得大规模、高度可用的分布…

    编程 2025-04-24
  • 分布式锁的实现与应用——以Redisson为例

    分布式锁是保障在分布式系统中多个节点之间资源互斥的重要手段,而Redisson是Redis官方推荐的Java客户端,不仅提供基于Java语言对Redis的操作接口,还提供了分布式锁…

    编程 2025-04-23
  • 详解SpringBoot分布式锁

    一、为什么需要分布式锁? 在分布式系统中,多个节点需要对同一资源进行并发访问和操作。如果没有分布式锁,很容易出现资源竞争问题,引发数据错误或系统崩溃的风险。 例如,假设有两个客户端…

    编程 2025-04-23
  • Zookeeper Docker:实现可扩展、可靠的分布式协调服务

    一、Docker容器技术 Docker是一种基于容器的虚拟化技术,它可以将应用程序及其依赖项打包为一个可移植、自包含的容器。Docker使得开发人员可以使用相同的环境在不同的计算机…

    编程 2025-04-23

发表回复

登录后才能评论