zoukankan      html  css  js  c++  java
  • 面试:业务开发中你用到了哪些算法?

    S哥:今天去面试啦,简历上写了一句“熟练运用算法于应用中”,面试官问我时,却不知道说啥(很尴尬)......

    ME:可以说说 hash 算法,先说说分库分表;然后一致性 hash;然后升华......

    年底了,确实有很多默默看机会的盆友,开始躁动了起来。身边很多选手也不例外,身边的 S 哥为了彰显自己牛掰,简历上斗胆撂了一句“熟练运用算法于应用中”,但是当面试官问起时,S 哥却被问的一愣一愣哒。

    鉴于此,不妨分享一下我的回答思路,看能否帮你争取点面试分。

    先说一个离我们比较近的应用场景。估计多数人还没有经历过分库分表,但是个人感觉,截止到目前稍微有点量级的应用,数据库可能没有拆分,但是订单表应该也被拆分的稀碎啦,这么说你可能不理解,不妨举个栗子。

    起初,原有的一张 T_ORDER 足矣满足业务需求,但是随着业务推广,订单表的数据日益增多,数据查询势必会越来越慢,性能是个问题。好的解决方案势必是分开,例如分成 T_ORDER_0、T_ORDER_1、T_ORDER_2 三张滚动表,但是到底该怎么实现这么个策略呢?

    码代码的不写点代码,确实不是那么回事儿!

    @Test
    public void splitTable() throws ParseException {
        //1. 取得当前数据库的时间,一定要用数据库的时间,因为服务器的时间可能会不同。
        //   此处为了示意,临时采用当前系统的时间
        Timestamp current = new Timestamp(System.currentTimeMillis());
    
    
        //2. 找一个你比较相中的时间点作为计算参考,例如 2009-7-1
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse("2009-7-1");
    
    
        //3. 计算当前时间与上面的参考时间相差的天数
        long t1 = current.getTime() - date.getTime();
        long t2 = 1000 * 60 * 60 * 24;
        int days = (int) (t1 / t2);
    
    
        //4. 相差的天数除 3 的余数来确定使用哪张订单表
        int lastname = days % 3;
        String tableName = "T_ORDER_" + lastname;
    
    
        System.out.println(tableName);
    }
    

      

    上面的代码来自于实际应用,可能代码不雅观,但是线上跑的却很好,所以也无心修理它。但是无论怎么跑,结果总会是 T_ORDER_0、T_ORDER_1、T_ORDER_2 来回切换。

    好了,知道了如何分表了,但是如果数据量依旧很大,是不是应该考虑分库啦,不多说,直接摘实际应用中一个较全的代码进行示意。

    @Test
    public void splitDbTable() throws Exception {
        // 分成 6 个库、共分成 1200 张表
        long dbNum = 6;
        long tableNum = 1200;
    
    
        //1. 按照某业务字段为拆分依据,例如按照身份证号进行拆分
        String splitField = "411424201802208888";
        //2. 对选择的业务字段的值取 crc32(字段数值化)
        java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
        crc32.update(splitField.getBytes("UTF-8"));
        long x = java.lang.Math.abs(crc32.getValue());
    
    
        //3. 计算数据库的下标
        long n = x % dbNum;
        String dbPos = String.format("%02d", n);
        System.out.println("数据库的下标:" + dbPos);
    
    
        //4. 计算数据库下表对应的下标
        long m = x % tableNum;
        String tablePos = String.format("%03d", m);
        System.out.println("表的下标:" + tablePos);
    }
    

      

    针对上面代码,咱们稍微抽象一点的去说一下(这块需要顿悟,尤其是数学不太好,脑子空间不够的同学,不妨拿个铅笔,算一算)。

    抽象正式开始啦,若有 M 个数据库主节点,数据表总计拆分成 N 张子表,拆表字段数值化转换为 X,则数据库实例的序号为  X % M ;数据表的序号为 X % N。

    例如:当主节点个数 M=6,总计拆表数 N=1200 时(单库内子表个数为 200),则数据库实例的序号 X % 6;数据表的序号为 X % 1200。

    于是:序号为 0 的数据库中,会有序号为 0,6,12,18… 的数据表;序号为 1 的数据库中,会有序号为 1,7,13,19… 的数据表;以此类推。

    拆表字段数值化机制:取拆表依据字段,对其取 crc32,之后取绝对值,即为上述“分库分表公式”中的 X。

    好了,到这距离咱们研发最近的 hash 算法就聊明白了,估计到这估计面试官也被你搞懵啦!

    但是面试中经常会谈及一致性 hash,到底要聊的是个啥呢?Memcached 里面用到了吗?Nginx 里面用到了吗?MapReduce 里面用到了吗?数据倾斜又是怎么回事呢?

    未完待续,且听下回分解。

  • 相关阅读:
    SAS学习笔记5 字符截取语句(index、compress、substr、scan函数)
    SAS学习笔记4 基本运算语句(lag、retain、_n_函数)
    SAS学习笔记3 输入输出格式(format、informat函数)
    SAS学习笔记2 基础函数应用
    特性与反射
    WebApi 接口返回值类型详解 ( 转 )
    C# 数据类型转化为byte数组
    关于.Net中Process和ProcessStartInfor的使用
    C#双缓冲解释
    如何获取到一个form中的所有子控件?
  • 原文地址:https://www.cnblogs.com/socoool/p/12629743.html
Copyright © 2011-2022 走看看