我希望使用spark streaming将protobuf消息存储在Hbase / HDFS中。我有以下两个问题
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中。
答案 0 :(得分:2)
问题1:
存储大量protobuf消息的有效方法是什么? 以及检索它们进行一些分析的有效方法?对于 它应该在Hbase或Should中存储为字符串/ byte [] 它们存储在HDFS等的镶木地板文件中。
我会推荐 - 将Proto-buf存储为Parquet AVRO文件(使用AVRO模式拆分为有意义的消息)。
这可以使用数据帧api spark 1.5及以上(PartiotionBy
和SaveMode.Append
)来实现
如果您存储为字符串或字节数组,则无法直接进行数据分析(查询原始数据)。
如果您使用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;
}