业务开发中你用到了哪些算法?

【这是一猿小讲的第 73 篇原创分享】

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 里面用到了吗?数据倾斜又是怎么回事呢?

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

你可能感兴趣的:(业务开发中你用到了哪些算法?)