美文网首页
关于一致性 Hash 环应用于课时类型比例划分的对比和思考

关于一致性 Hash 环应用于课时类型比例划分的对比和思考

作者: 啤酒代码 | 来源:发表于2019-04-17 16:23 被阅读0次

    背景

    目前课时是没有类型的我们希望针对课时增加类型的区分并且控制比例(例如: TRIAL / MAJOR = 3 / 1)

    要求

    1. 不通过数据库记录已存在的课时类型信息
    2. 要保证增加 1 课时后,之前的课时类型尽量保持不变
    3. 当类型占比设置发生变化时,数据移动最小

    结论

    选用第 4 种方案目前测试结果第 3、4 种方案效果较好,但从简易实现程度和比例控制来看,选用第 4 种方案更佳。

    划分方案

    1. 按时间顺序划分

    image.png
    弊端
    1. 按时间顺序分:时间不均衡,可能导致 TRIAL 课集中在前几天,后面两天想约 TRIAL 约不到

    2. 按时间均分

    image.png
    弊端
    1. 按时间均分: 比例调整后,划分位置变动较大

    以下两种方式是通过对 课时信息的 Time 字段 进行 HASH 并排序后进行类型划分好处: 可以尽量保证新课时加入集合中后,集合中已存在的课时类型变化最小

    3. 通过一致性 Hash 环划分

    什么是 一致性 Hash 环?一致性哈希算法

    占比之和等于总节点数,比如 TRIAL / MJAOR 为 3 / 1 , 根据占比数量生成对应的节点,如下:

    image.png 节点分布如下: image.png

    如果节点分布过于分散,可能导致数据落点不均匀,如下图最终分配 2 个 Major, 2 个 Trial。

    image.png

    所以要生成对应的虚拟节点,当教师放课时根据 课时信息的 Time 字段 生成 HASH 后落入以下节点中,最终落入节点的占比即为约课占比

    真实节点
    image.png
    虚拟节点
    image.png
    HASH 环
    最终得到 1 个 MAJOR,3 个 TRIAL,形成 3 : 1 image.png

    4. 通过 HASH 散列并排序后按比例切分

    这个方案是拿到一个课时集合,比如:

    "2019-01-14 18:30:00"
    "2019-01-14 19:00:00"
    "2019-01-15 18:30:00"
    "2019-01-15 19:30:00"
    

    把以上集合直接放入 HashSet 得到一个无序的列表

    "2019-01-14 18:30:00"
    "2019-01-15 19:30:00"
    "2019-01-14 19:00:00"
    "2019-01-15 18:30:00"
    

    之后按照比例,如:3 / 1 , 分割后得到:

    TRIAL:
    "2019-01-14 18:30:00"
    "2019-01-15 19:30:00"
    "2019-01-14 19:00:00"
    
    MAJOR:
    "2019-01-15 18:30:00"
    

    实例代码如下:

            double trialRatio = 3;
            double majorRatio = 1;
    
            String[] keys = {
                      "2019-01-14 18:30:00"
                    , "2019-01-14 19:00:00"
                    , "2019-01-15 18:30:00"
                    , "2019-01-15 19:30:00"
            };
    
            HashSet<String> hashSet = new HashSet<>(keys);
            List<String> timeList = Lists.newArrayList(hashSet);
            double t = Math.round((double) keys.length / (trialRatio + majorRatio) * trialRatio);
            System.out.println("\nTRIAL 课");
            timeList.subList(0, (int)t).forEach(System.out::println);
            System.out.println("\nMAJOR 课");
            timeList.subList((int)t, timeList.size()).forEach(System.out::println);
    

    参考链接:
    一致性哈希算法的理解与实践
    Consistent_hashing
    Consistent Hashing in Cassandra

    相关文章

      网友评论

          本文标题:关于一致性 Hash 环应用于课时类型比例划分的对比和思考

          本文链接:https://www.haomeiwen.com/subject/gfvnwqtx.html