zoukankan      html  css  js  c++  java
  • ip白名单算法(pdd活跃用户)

    https://www.hellojava.com/a/76003.html

    1)用ip地址字符串hash,显然太low

    2)ip地址字符串转换为long,ipv4总共2^32个(4g),一个bit存一个ip地址,4g个bit=0.5g个字节

    故建立长度为0.5g的byte数组,接下去要确定的是白ip所在的位置

    所在数组索引=ip/8

    在byte中位索引=ip%8=ip&(8-1)

        /**
         * ipv4总共2^32个(4g)
         * 一个bit存一个ip地址,4g个bit=0.5g个字节
         */
        private static byte [] pool = new byte[512*1024*1024];
    
        // 0-255 <子ip字符串,long> 缓存
        private static ConcurrentHashMap<String, Long> cache = new ConcurrentHashMap<>(256);
    
        public static void add(String ip) {
            long ipLong = ipToLong(ip);
            long index = ipLong / 8;
            long pos = ipLong & (8-1);相当于ipLong % 8
            pool[(int)index] |= 1 << pos;
        }
    
        public static boolean check(String ip) {
            long ipLong = ipToLong(ip);
            long index = ipLong / 8;
            long pos = ipLong & (8-1);
            return (pool[(int)index] & (1<<pos)) > 0;
        }
    

    其中ip字符串转数字涉及到一个缓存,如"192"直接缓存,下一次不需要再转数字

     如:

    192.168.1.3

    为3232235779,

    byte index = 404029472.375

    bit index = 3

        public static void add(String ip) {
            long ipLong = ipToLong(ip);
        //    System.out.println(ipLong);
            long index = ipLong / 8;
        //    System.out.println(index);
            long pos = ipLong & (8-1);
        //    System.out.println(1 << pos);
            pool[(int)index] |= 1 << pos;
        }
    

    程序输出:

    3232235779
    404029472

    8 二进制为 00001000

    对该方式进行压力测试,CPU密集型,开4个线程,每个线程跑200w次

        public static void test() {
            check("192.168.1.3");
            check("192.168.1.4");
        }
    
        // 4并发数 缓存3s执行完,不缓存5s,qps约2百万
        // 隔壁需要6s
        public static void main(String [] f) throws InterruptedException {
            String ip = "192.168.1.3";
            add(ip);
            System.out.println(check(ip));
            System.out.println(check("192.168.2.3"));
    
            String ip1= "192.168.1.3";
            IPFiliterTest.addWhiteIpAddress(ip1);
    
            final int threadCount = 4;
            CountDownLatch countDownLatchMain = new CountDownLatch(threadCount);
            CountDownLatch countDownLatchSub = new CountDownLatch(1);
            
    
            for(int i=0; i<threadCount; ++i) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            countDownLatchSub.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        for(int j=0; j<1000000; ++j)
                            test();
                        //IPFiliterTest.test();
                        countDownLatchMain.countDown();
    
                    }
                }).start();
            }
            System.out.println(System.currentTimeMillis());
            countDownLatchSub.countDown();
            countDownLatchMain.await();
            System.out.println(System.currentTimeMillis());
        }
    

    结果:

    总共800w次在4s中完成(3s为缓存,5s为不缓存),qps=200w

    使用原作者的需要6s

    10线程5.8s,总共2000w次调用,qps=333w

    100线程40.8s,总共2亿次调用,qps=490w

    使用benchmark

    4线程和10线程,一次预热3次迭代都是290w*2=580w左右的qps

     4thr.  IpPool.test  thrpt    3  2908446.729 ± 178674.949  ops/s

    10 thr IpPool.test  thrpt    3  2860266.544 ± 505878.277  ops/s

    该算法使用内存至少512m,稍显大,可以使用外部存储集群,比如redis bit结构,程序分片

    总共4g个比特,分为4片,每片1g个bit 128m内存,那么

    服务器索引=x/1g

    路由后的ip=x%1g=x&(2^30-1)

    这种方式也可以用于活跃用户统计

    (拼多多面试真题:如何用Redis统计独立用户访问量https://blog.csdn.net/weixin_38405253/article/details/92285696),

    设20亿用户,每个用户一个bit,总共需要20亿/8个字节=238M内存

    缺点就是如果用户稀疏,会浪费内存,对uid hash空间更小

  • 相关阅读:
    洛谷-P1855 榨取kkksc03
    Error: ORA-06502: PL/SQL: 数字或值错误 : character string buffer too small(触发器中使用系统动态视图导致)
    jwt ctf
    apktool+nuclei mobile
    Subdomain Takeover via Fastly ( Steps )
    乱七八糟
    Recon
    推荐几个我感觉不错的tips
    子域名收集
    清除Cookie的数据
  • 原文地址:https://www.cnblogs.com/silyvin/p/11731987.html
Copyright © 2011-2022 走看看