面试官:如何在千万级数据中查询 10W 的数据,都有什么方案?

前言

在开发中遇到一个业务诉求,需要在千万量级的底池数据中筛选出不超过 10W 的数据,并根据配置的权重规则进行排序、打散(如同一个类目下的商品数据不能连续出现 3 次)。

下面对该业务诉求的实现,设计思路和方案优化进行介绍,对「千万量级数据中查询 10W 量级的数据」设计了如下方案

  1. 多线程 + CK 翻页方案
  2. ES scroll scan 深翻页方案
  3. ES + Hbase 组合方案
  4. RediSearch + RedisJSON 组合方案

初版设计方案

整体方案设计为:

  1. 先根据配置的「筛选规则」,从底池表中筛选出「目标数据」
  2. 在根据配置的「排序规则」,对「目标数据」进行排序,得到「结果数据」

技术方案如下:

  1. 每天运行导数任务,把现有的千万量级的底池数据(Hive 表)导入到 Clickhouse 中,后续使用 CK 表进行数据筛选。
  2. 将业务配置的筛选规则和排序规则,构建为一个「筛选 + 排序」对象 SelectionQueryCondition
  3. 从 CK 底池表取「目标数据」时,开启多线程,进行分页筛选,将获取到的「目标数据」存放到 result 列表中。
//分页大小  默认 5000
int pageSize = this.getPageSize();
//页码数
int pageCnt = totalNum / this.getPageSize() + 1;

List> result = Lists.newArrayList();
List>>> futureList = new ArrayList<>(pageCnt);

//开启多线程调用
for (int i = 1; i <= pageCnt; i++) {
    //将业务配置的筛选规则和排序规则 构建为 SelectionQueryCondition 对象
    SelectionQueryCondition selectionQueryCondition = buildSelectionQueryCondition(selectionQueryRuleData);
    selectionQueryCondition.setPageSize(pageSize);
    selectionQueryCondition.setPage(i);
    futureList.add(selectionQueryEventPool.submit(new QuerySelectionDataThread(selectionQueryCondition)));
}

for (Future>> future : futureList) {
    //RPC 调用
    List> queryRes = future.get(20, TimeUnit.SECONDS);
    if (CollectionUtils.isNotEmpty(queryRes)) {
        // 将目标数据存放在 result 中
        result.addAll(queryRes);
    }
}

对目标数据 result 进行排序,得到最终的「结果数据」。

推荐一个开源免费的 Spring Boot 最全教程:

https://github.com/javastacks/spring-boot-best-practice

CK分页查询

在「初版设计方案」章节的第 3 步提到了「从 CK 底池表取目标数据时,开启多线程,进行分页筛选」。此处对 CK 分页查询进行介绍。

封装了 queryPoolSkuList

你可能感兴趣的:(java,spring,spring,boot)