本章节主要为您介绍如何基于表格存储实现海量气象格点数据解决方案。

基于方案设计,表格存储实现了一个Tablestore-Grid的library,基于这个Library您可以非常方便的实现气象格点数据的存储、查询和管理。提供以下接口:
public interface GridStore {
    /**
     * 创建相关的meta、data表,数据录入前调用。
     * @throws Exception
     */
    void createStore() throws Exception;

    /**
     * 写入gridDataSet的meta信息。
     * @param meta
     * @throws Exception
     */
    void putDataSetMeta(GridDataSetMeta meta) throws Exception;

    /**
     * 更新meta信息。
     * @param meta
     * @throws Exception
     */
    void updateDataSetMeta(GridDataSetMeta meta) throws Exception;

    /**
     * 通过gridDataSetId获取meta。
     * @param dataSetId
     * @return
     * @throws Exception
     */
    GridDataSetMeta getDataSetMeta(String dataSetId) throws Exception;

    /**
     * // 创建meta表的多元索引。
     * @param indexName
     * @param indexSchema
     * @throws Exception
     */
    void createMetaIndex(String indexName, IndexSchema indexSchema) throws Exception;

    /**
     * 通过多种查询条件来查询符合条件的数据集。
     * @param indexName 多元索引名。
     * @param query 查询条件,可以通过QueryBuilder构建。
     * @param queryParams 查询相关参数,包括offset、limit、sort等。
     * @return
     * @throws Exception
     */
    QueryGridDataSetResult queryDataSets(String indexName, Query query, QueryParams queryParams) throws Exception;

    /**
     * 获取GridDataWriter用于写入数据。
     * @param meta
     * @return
     */
    GridDataWriter getDataWriter(GridDataSetMeta meta);

    /**
     * 获取GridDataFetcher用于读取数据。
     * @param meta
     * @return
     */
    GridDataFetcher getDataFetcher(GridDataSetMeta meta);

    /**
     * 释放资源。
     */
    void close();
}

public interface GridDataWriter {
    /**
     * 写入一个二维平面。
     * @param variable 变量名。
     * @param t 时间维的值。
     * @param z 高度维的值。
     * @param grid2D 平面数据。
     * @throws Exception
     */
    void writeGrid2D(String variable, int t, int z, Grid2D grid2D) throws Exception;
}

public interface GridDataFetcher {
    /**
     * 设置要查询的变量。
     * @param variables
     * @return
     */
    GridDataFetcher setVariablesToGet(Collection<String> variables);

    /**
     * 设置要读取的各维度起始点和大小。
     * @param origin 各维度起始点。
     * @param shape 各维度大小。
     * @return
     */
    GridDataFetcher setOriginShape(int[] origin, int[] shape);

    /**
     * 获取数据。
     * @return
     * @throws Exception
     */
    GridDataSet fetch() throws Exception;
}

数据录入



数据录入流程可以分为三部分:
  • 写入putDataSetMeta接口写入数据集的meta信息。
  • 通过GridDataWriter录入整个数据集的数据。
  • 通过updateDataSetMeta接口更新数据集的meta信息,标记数据已经录入完成。

示例如下:

以下示例中读取一个NetCDF(气象格点数据常用的格式)文件,然后将其中的数据通过GridDataWriter录入到表格存储中。通过GridDataWriter每次写入时,只能写入一个二维平面,所以需要在外层进行3层循环,分别枚举变量维、时间维、高度维的值,然后读取对应的二维平面的数据进行录入。

public void importFromNcFile(GridDataSetMeta meta, String ncFileName) throws Exception {
    GridDataWriter writer = tableStoreGrid.getDataWriter(meta);
    NetcdfFile ncFile = NetcdfFile.open(ncFileName);
    List<Variable> variables = ncFile.getVariables();
    for (Variable variable : variables) {
        if (meta.getVariables().contains(variable.getShortName())) {
            for (int t = 0; t < meta.gettSize(); t++) {
                for (int z = 0; z < meta.getzSize(); z++) {
                    Array array = variable.read(new int[]{t, z, 0, 0}, new int[]{1, 1, meta.getxSize(), meta.getySize()});
                    Grid2D grid2D = new Grid2D(array.getDataAsByteBuffer(), variable.getDataType(),
                            new int[] {0, 0}, new int[] {meta.getxSize(), meta.getySize()});
                    writer.writeGrid2D(variable.getShortName(), t, z, grid2D);
                }
            }
        }
    }
}

数据查询



GridDataFetcher支持对五维数据进行任意维度的查询。第一维是变量维,通过setVariablesToGet接口设置要读取哪些变量,其余四维通过设置起始点(origin)和读取的大小(shape)就可以实现任意维度读取。

public Array queryByTableStore(String dataSetId, String variable, int[] origin, int[] shape) throws Exception {
      GridDataFetcher fetcher = this.tableStoreGrid.getDataFetcher(this.tableStoreGrid.getDataSetMeta(dataSetId));
      fetcher.setVariablesToGet(Arrays.asList(variable));
      fetcher.setOriginShape(origin, shape);
      Grid4D grid4D = fetcher.fetch().getVariable(variable);
      return grid4D.toArray();
}

多条件检索数据集



本方案中,对meta表建立多元索引后,可以支持通过各种组合条件来进行数据集检索,查询出符合条件的数据集,这个功能对于气象管理系统来说非常重要。

示例如下:

假设我们要查询已经完成入库的,创建时间为最近一天的,来源为ECMWF(欧洲中期天气预报中心)或者NMC(全国气象中心),精度为1km的气象预报,并按照创建时间从新到老排序,可以用以下代码实现:

查询条件: (status == DONE) and (create_time > System.currentTimeMillis - 86400000) and (source == "ECMWF" or source == "NMC") and (accuracy == "1km")

QueryGridDataSetResult result = tableStoreGrid.queryDataSets(
        ExampleConfig.GRID_META_INDEX_NAME,
        QueryBuilder.and()
                .equal("status", "DONE")
                .greaterThan("create_time", System.currentTimeMillis() - 86400000)
                .equal("accuracy", "1km")
                .query(QueryBuilder.or()
                        .equal("source", "ECMWF")
                        .equal("source", "NMC")
                        .build())
                .build(),
        new QueryParams(0, 10, new Sort(Arrays.<Sort.Sorter>asList(new FieldSort("create_time", SortOrder.DESC)))));

这一部分功能利用了表格存储的多元索引,多元索引可以实现多字段组合查询、模糊查询、全文检索、排序、范围查询、嵌套查询、空间查询等功能,给元数据管理场景提供了强大的底层能力。

代码的获取

可以在github上获取Tablestore-Grid的实现代码和示例代码

专家服务

表格存储 提供专业的免费的技术咨询服务,欢迎加入我们的钉钉讨论群。