使用Spark流在Hbase / HDFS中保存protobuf

时间:2016-06-22 09:10:17

标签: apache-spark hbase hdfs protocol-buffers spark-streaming

我希望使用spark streaming将protobuf消息存储在Hbase / HDFS中。我有以下两个问题

  1. 存储大量protobuf的有效方法是什么? 消息和检索它们的有效方法 分析?例如,它们应该在Hbase中存储为字符串/ byte []还是存储在HDFS等的镶木地板文件中。
  2. 如何应用protobuf的层次结构 消息存储?我的意思是,嵌套元素是否应该被展平     在存储之前,或者有没有任何机制来存储它们?     如果嵌套元素是集合或映射它们应该是     爆炸并存储为多行?
  3. Protobuf消息的示例结构如下所示

    >     +--MsgNode-1
    >       +--Attribute1 - String
    >       +--Attribute2 - Int
    >       +--MsgNode-2
    >         +--Attribute1 - String
    >         +--Attribute2 - Double
    >         +--MsgNode-3 - List of MsgNode-3's
    >           +--Attribute1 - Int
    

    我打算使用Spark流来收集protobuf消息作为字节并将它们存储在Hbase / HDFS中。

1 个答案:

答案 0 :(得分:2)

问题1:

  

存储大量protobuf消息的有效方法是什么?   以及检索它们进行一些分析的有效方法?对于   它应该在Hbase或Should中存储为字符串/ byte []   它们存储在HDFS等的镶木地板文件中。

我会推荐 - 将Proto-buf存储为Parquet AVRO文件(使用AVRO模式拆分为有意义的消息)。

这可以使用数据帧api spark 1.5及以上(PartiotionBySaveMode.Append)来实现

请参阅此a-powerful-big-data-trio

如果您存储为字符串或字节数组,则无法直接进行数据分析(查询原始数据)。

如果您使用cloudera,可以使用impala(支持parquet-avro)查询rawdata。

问题2:

  

protobuf消息的层次结构应该如何   存储在哪里?我的意思是,嵌套元素之前是否应该被展平   存储,还是有任何机制来存储它们?如果是嵌套的   元素是集合或地图,如果它们被爆炸并存储为   多行?

如果您使用spark streaming以原始格式存储数据,您将如何查询业务是否要查询并知道他们收到的数据类型(此要求非常常见)。

首先,您必须了解您的数据(即protobuf中不同消息之间的关系,以便您可以决定单行或多行)然后开发protobuf解析器来解析protobuf的消息结构。根据您的数据,将其转换为avro通用记录保存为镶木地板文件。

提示:

protobuf解析器可以根据您的要求以不同的方式开发。 其中一种通用方式如下例所示。

public SortedMap<String, Object> convertProtoMessageToMap(GeneratedMessage src) {

    final SortedMap<String, Object> finalMap = new TreeMap<String, Object>();
    final Map<FieldDescriptor, Object> fields = src.getAllFields();

    for (final Map.Entry<FieldDescriptor, Object> fieldPair : fields.entrySet()) {

        final FieldDescriptor desc = fieldPair.getKey();

        if (desc.isRepeated()) {
            final List<?> fieldList = (List<?>) fieldPair.getValue();
            if (fieldList.size() != 0) {
                final List<String> arrayListOfElements = new ArrayList<String>();
                for (final Object o : fieldList) {
                    arrayListOfElements.add(o.toString());
                }
                finalMap.put(desc.getName(), arrayListOfElements);
            }
        } else {

            finalMap.put(desc.getName(), fieldPair.getValue().toString());

        }

    }
    return finalMap;
}