从概率统计看限流阈值问题

简介: 服务提供方所在的应用A有100台机器,某个调用方需要申请该应用的某个服务1000 QPS的调用量,根据经验,如果A应用的单机限流值配置成10,应该会有比较多的额度内的流量被限制住,如果配置的太高,又会有稳定性风险,限流值应该配置成多少合适呢?

问题    

      “服务提供方所在的应用A有100台机器,某个调用方需要申请该应用的某个服务1000 QPS的调用量,根据经验,如果A应用的单机限流值配置成10,应该会有比较多的额度内的流量被限制住,如果配置的太高,又会有稳定性风险,限流值应该配置成多少合适呢?”

 

分析

        把限流的问题抽象一下:若单机QPS平均值为m,求实际落到该机器的QPS 不超过k的概率P(x<=k),知道了这个概率分布情况,我们就能知道限流值n设置为多少合适,或者能相对量化的分析所配置的限流的作用效果。

       为了便于分析,我们不妨假设,在不扩缩容的某个时间段,流量落到某台机器的概率是稳定的,而且我们知道每次流量落到哪台机器是独立事件,那么在单位时间内,落在某台机器的流量x可以认为是服从泊松分布的。

结论

故实际落到该机器的QPS x<=k 的概率为:

image.png

n三k

m

P(X<-K)二

xe-m

n!

nE0

   使用该公式,代入不同的k和m,可以得到单机QPS平均值m取不同值时,实际打到某台机器的流量x不超过k的概率值(精确到百分比小数点后5位)。

m=1 m=5 m=10 m=20
k x<k的概率 k x<k的概率 k x<k的概率 k x<k的概率
0 36.78794% 0 0.67379% 0 0.00454% 0 0.00000%
1 73.57589% 1 4.04277% 1 0.04994% 1 0.00000%
2 91.96986% 2 12.46520% 2 0.27694% 2 0.00005%
3 98.10118% 3 26.50259% 3 1.03361% 3 0.00032%
4 99.63402% 4 44.04933% 4 2.92527% 4 0.00169%
5 99.94058% 5 61.59607% 5 6.70860% 5 0.00719%
6 99.99168% 6 76.21835% 6 13.01414% 6 0.02551%
7 99.99898% 7 86.66283% 7 22.02206% 7 0.07786%
8 99.99989% 8 93.19064% 8 33.28197% 8 0.20873%
9 99.99999% 9 96.81719% 9 45.79297% 9 0.49954%
10 1 10 98.63047% 10 58.30398% 10 1.08117%
11 1 11 99.45469% 11 69.67761% 11 2.13868%
12 1 12 99.79811% 12 79.15565% 12 3.90120%
13 1 13 99.93020% 13 86.44644% 13 6.61276%
14 1 14 99.97737% 14 91.65415% 14 10.48643%
15 1 15 99.99310% 15 95.12596% 15 15.65131%
16 1 16 99.99801% 16 97.29584% 16 22.10742%
17 1 17 99.99946% 17 98.57224% 17 29.70284%
18 1 18 99.99986% 18 99.28135% 18 38.14219%
19 1 19 99.99997% 19 99.65457% 19 47.02573%
20 1 20 99.99999% 20 99.84117% 20 55.90926%
21 1 21 100.00000% 21 99.93003% 21 64.36976%
22 1 22 100.00000% 22 99.97043% 22 72.06113%
23 1 23 100.00000% 23 99.98799% 23 78.74928%
24 1 24 100.00000% 24 99.99531% 24 84.32274%
25 1 25 1 25 0.99998232 25 88.78150%
26 1 26 1 26 0.99999358 26 92.21132%
27 1 27 1 27 0.99999775 27 94.75193%
28 1 28 1 28 0.99999924 28 96.56665%
29 1 29 1 29 0.99999975 29 97.81818%
30 1 30 1 30 0.99999992 30 98.65253%
31 1 31 1 31 0.99999998 31 99.19082%
32 1 32 1 32 0.99999999 32 99.52726%
33 1 33 1 33 1 33 99.73116%
34 1 34 1 34 1 34 99.85110%
35 1 35 1 35 1 35 99.91963%
36 1 36 1 36 1 36 99.95771%
37 1 37 1 37 1 37 99.97829%
38 1 38 1 38 1 38 99.98912%
39 1 39 1 39 1 39 99.99468%

  通过该表格可以发现,如果要保证99.9%的流量不被限流:

  当单机QPS平均值为1的时候,我们的限流值要设置为不小于5.

  当单机QPS平均值为5的时候,我们的限流值要设置为不小于12.

  当单机QPS平均值为10的时候,我们的限流值要设置为不小于21.

  当单机QPS平均值为20的时候,我们的限流值要设置为不小于35.

  如果需要看更详细的概率分布,可以用下面这段简单的工具代码来生成,需要注意的是m调大的时候,实际QPS的上限MAX_K要相应的调大。

package com.cainiao.hyena;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
 * [Poisson分布概率计算工具]
 *
 * @author jianping.pjp created on 2020/12/8 下午11:29
 * Copyright 2020 (C) <Alibaba Global>
 */
public class PoissonTest {
    //在指定QPS平均值的前提下,我们猜测实际最大能打到的QPS,可根据实际跑出的结果来调整,这个值是和平均值正相关的
    private static final int MAX_K = 40;
    public static void main(String[] args) {
        int m = 10;
        BigDecimal p = new BigDecimal(0);
        for (int k = 0; k < MAX_K; k++) {
            BigDecimal x = p2(m, k);
            p = p.add(x);
            System.out.println(k + "," + p.setScale(10, RoundingMode.DOWN).doubleValue());
        }
    }
    private static BigDecimal p2(int m, int k) {
        BigDecimal a = new BigDecimal(1);
        if (k == 0) {
            return new BigDecimal(Math.exp(-m));
        }
        BigDecimal r = new BigDecimal(-m).divide(new BigDecimal(k), 100, RoundingMode.DOWN);
        BigDecimal b = new BigDecimal(Math.exp(r.doubleValue()));
        for (int n = 1; n <= k; n++) {
            BigDecimal an = new BigDecimal(m).divide(new BigDecimal(n), 100, RoundingMode.DOWN).multiply(b);
            a = a.multiply(an);
        }
        return a;
    }
}

 

验证

通过下面验QPS模拟生成工具代码可以验证我们的猜测,以下代码对平均值10 QPS做了100万次模拟试验,实验的结果符合我们的猜测。

package com.cainiao.hyena;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
 * [模拟QPS实现验证]
 *
 * @author jianping.pjp created on 2020/12/10 下午1:07
 * Copyright 2020 (C) <Alibaba Global>
 */
public class PoissonVerification {
    //在指定QPS平均值的前提下,我们猜测实际最大能打到的QPS,可根据实际跑出的结果来调整,这个值是和平均值正相关的
    private final static int MAX_K = 40;
    public static void main(String [] args){
        Random r = new Random();
        //每次实验打到指定机器的实际QPS
        Map<Integer,Integer> map = new HashMap<>();
        //模拟QPS平均值
        int qps = 10;
        //实现次数
        int experimentsTimes = 1000000;
        for(int i=0;i<qps*experimentsTimes;i++){
            int n = r.nextInt(experimentsTimes);
            Integer c= map.get(n);
            if(c==null){
                c = 0;
            }
            c++;
            map.put(n,c);
        }
        for(int k=0;k<MAX_K;k++){
            //实际QPS不超过K的实验次数
            int lk = 0;
            for(int i=0;i<experimentsTimes;i++){
                Integer c = map.get(i);
                if(null ==c || c<=k){
                    lk++;
                }
            }
            double ratio = (double)lk/experimentsTimes;
            System.out.println(k+","+ratio);
        }
    }
}
                     m=10
k  x<k的概率 试验结果
0 0.00454% 0.00510%
1 0.04994% 0.05090%
2 0.27694% 0.28200%
3 1.03361% 1.02100%
4 2.92527% 2.91860%
5 6.70860% 6.70020%
6 13.01414% 12.99690%
7 22.02206% 21.95120%
8 33.28197% 33.25910%
9 45.79297% 45.80050%
10 58.30398% 58.31790%
11 69.67761% 69.67210%
12 79.15565% 79.15300%
13 86.44644% 86.48280%
14 91.65415% 91.68780%
15 95.12596% 95.15310%
16 97.29584% 97.30320%
17 98.57224% 98.56930%
18 99.28135% 99.28800%
19 99.65457% 99.66060%
20 99.84117% 99.84590%
21 99.93003% 99.92790%
22 99.97043% 99.97050%
23 99.98799% 99.98880%
24 99.99531% 99.99570%
25 0.99998232 99.99870%
26 0.99999358 99.99930%
27 0.99999775 99.99990%
28 0.99999924 1
29 0.99999975 1
30 0.99999992 1
31 0.99999998 1
32 0.99999999 1
33 1 1

相关资料

http://www.ruanyifeng.com/blog/2015/06/poisson-distribution.html

https://www.zhihu.com/question/26441147/answer/208718584

目录
相关文章
|
JavaScript 前端开发 架构师
12个开源免费的程序员简历模板
12个开源免费的程序员简历模板
1435 0
|
存储 运维 NoSQL
Redis分片集群中数据是怎么存储和读取
为了实现水平扩展和高可用性,Redis采用了分片机制。分片是将数据按照一定规则分配到多个节点上进行存储,每个节点只负责部分数据的存储和处理。这样可以提高系统的吞吐量和可扩展性。
711 0
|
3月前
|
监控 数据挖掘 API
利用拼多多 API 接口,实现拼多多店铺物流时效优化
在电商竞争激烈的今天,物流时效直接影响拼多多店铺的客户满意度与复购率。本文介绍如何通过拼多多开放平台的 API 接口,自动化获取订单与物流数据,分析时效瓶颈并制定优化策略。内容涵盖 API 基本功能、物流数据分析、智能优化方法及 Python 实现示例,帮助商家提升配送效率,降低退货率,增强用户体验与店铺竞争力。
448 0
|
存储 Kubernetes Cloud Native
告别数据丢失的噩梦!PersistentVolume全攻略,让你轻松玩转Kubernetes数据持久化秘籍!
【8月更文挑战第25天】随着容器技术的发展,Kubernetes已成为云原生应用的主流部署平台。然而,数据持久化成为一个亟待解决的问题。Kubernetes通过PersistentVolume(PV)提供了解决方案。PV是一种存储资源对象,它抽象出底层存储技术(例如Ceph、GlusterFS或NFS),让用户仅需关注存储容量和访问模式等属性。PV由管理员创建与维护,Pod通过PersistentVolumeClaim(PVC)请求存储资源。本文详细介绍了PV的工作原理、配置方法及示例,帮助读者更好地理解和应用此功能。
325 2
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
301 8
|
安全 程序员 C++
C++一分钟之-原子操作与线程安全
【6月更文挑战第27天】**C++的`std::atomic`提供线程安全的原子操作,解决多线程数据竞争。涵盖原子操作概念、应用、问题与对策。例如,用于计数器、标志位,但选择数据类型、内存顺序及操作组合需谨慎。正确使用能避免锁,提升并发性能。代码示例展示自旋锁和线程安全计数。了解并恰当运用原子操作至关重要。**
334 1
|
Web App开发 测试技术 C++
Playwright安装与Python集成:探索跨浏览器测试的奇妙世界
Playwright是新兴的跨浏览器测试工具,相比Selenium,它支持Chrome、Firefox、WebKit,执行速度快,选择器更稳定。安装Playwright只需一条`pip install playwright`的命令,随后的`playwright install`会自动添加浏览器,无需处理浏览器驱动问题。这一优势免去了Selenium中匹配驱动的烦恼。文章适合寻求高效自动化测试解决方案的开发者。
|
SQL 数据库 数据安全/隐私保护
harbor修改密码
在Harbor `v2.9.0`中,忘记密码可使用以下方法强制重置:通过`docker exec`进入harbor-db容器,使用SQL命令`update harbor_user set salt=&#39;&#39;,password=&#39;&#39; where user_id = 1;`清空admin密码。然后重启Harbor,系统将要求初始化新密码。注意此操作涉及数据库交互,需谨慎执行。
1607 0
|
消息中间件 Java Kafka
Spring 事务的独门绝技:钩子函数的使用技巧
经过前面对Spring AOP、事务的总结,我们已经对它们有了一个比较感性的认知了。今天,我继续安利一个独门绝技:Spring 事务的钩子函数。单纯的讲技术可能比较枯燥乏味。接下来,我将以一个实际的案例来描述Spring事务钩子函数的正确使用姿势。
Spring 事务的独门绝技:钩子函数的使用技巧
|
SQL Java 数据库连接
SpringBoot中事务执行原理分析(六)
SpringBoot中事务执行原理分析(六)
574 0