一般而言,Json具有良好的表达性,在数据交换过程中被大量使用,但在大数据的环境中,由于Json的冗余相对来说较高,导致要存储的数据量很大,极大的浪费了服务器存储空间,本文通过将Json转为Avro数据格式,压缩数据,以供给后面处理提供提供便利。
在处理之前,我们先普及一下相关的概念。
1、Json
Json是一种轻量级的数据交换格式。它基于 ECMAScript 规范的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。在互联网数据交换中大量被使用。
直观的来看,Json有以下的格式:
{"Name1": "Brett", "Name2": "McLaughlin"}
即:键值对
对于一般使用者来说,最常见的使用情况便是通过Json[‘Key’]去取到对应的Value。
关于Json,在这里就不展开了。
2、Avro
Avro是Hadoop的子项目,适用于大数据下的数据存储。
它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro提供的机制使动态语言可以方便地处理Avro数据。
Avro特点( 对于后两个特点我还没体会到):
丰富的数据结构类型;
Ø 快速可压缩的二进制数据形式,对数据二进制序列化后可以节约数据存储空间和网络传输带宽;
Ø 存储持久数据的文件容器;
Ø 可以实现远程过程调用RPC;
Ø 简单的动态语言结合功能。
简单的说,Avro有两种表达形式,由于其依赖于schema的特性,所以在表达时就存在一种适用于表达schema的json表达方式,这种表达方式一般用于定义如:
namespace":"example.avro",
"type": "record",
"name": "User",
"fields": [
{"name": "name", "type":"string"},
int", "null"]},
{"name": "favorite_color", "type":["string", "null"]}
]
}
在定义Schema之后Avro会根据Schema的格式去对数据进行处理,并存储为特殊的二进制形式,在这里存储方式就不展开讨论了,有兴趣的同学可以自行搜索像:
http://langyu.iteye.com/blog/708568点击打开链接
这样的文章
因为有schema的指导。这样就允许了每个数据都没有前缀开销,所以Avro的序列化效果非常好,适用于存储海量数据。
2、序列化与反序列化
在本文中,我做了这样的工作:将数据从Json格式反序列化成了自定义对象,在将自定义对象序列化成Avro的二进制形式,主要实现语言为python,所用库confluent_kafka_python
流程如下:
1、实例化自定义对象Object
2、将Json对象的value写入Object相应的属性中
3、定义Schema,在这里Schema的定义分为key_schema和value_schema
4、实例化Avro生产者进行生产。
#Author:Silence Celin
from confluent_kafka import avro
from confluent_kafka.avro import AvroProducer
from confluent_kafka import Consumer, KafkaException, KafkaError
import sys
import json
if __name__ =="__main__":
if len(sys.argv) != 5:
sys.stderr.write('Usage: %s <bootstrap-brokers> <topic>\n' % sys.argv[0])
sys.exit(1)
#config
broker = sys.argv[1]
print broker
schema_registry_url=sys.argv[2]
print schema_registry_url
#config avroProducer
avrotopic = sys.argv[3]
value_schema=avro.load('Object.avsc')
key_schema=avro.load('Id.avsc')
avroconf={'bootstrap.servers':broker,'schema.registry.url':schema_registry_url}
#config jsonComsumer
jsontopic=sys.argv[4]
print jsontopic
jsonlist=[jsontopic]
jsonconf={'group.id':'test','bootstrap.servers':broker}
#create avroProducer
avroProducer=AvroProducer(avroconf,default_key_schema=key_schema,default_value_schema=value_schema)
#create jsonConsumer
jsonConsumer=Consumer(jsonconf)
jsonConsumer.subscribe(jsonlist)
while True:
#Json consume
msg=jsonConsumer.poll(timeout=1.0)
#print data.value()
if msg is None:
print('OK: poll() timeout')
continue
elif msg.error():
print('OK: consumer error: %s' % msg.error().str())
message=json.loads(msg)
#Json Deserialize -> Avro Serialize Config
object=Object()
object.setattribute(Object_data=message)
value={
//参照confluent_kafka官方文档自行定义
}
key=id
#Avro produce
try:
avroProducer.produce(topic=avrotopic,value=value,key=key, callback=delivery_callback)
except BufferError as e:
sys.stderr.write('%% Avro producer queue is full ' \
'(%d messages awaiting delivery): try again\n' %
len(avroProducer))
以上代码没有测试,如有问题欢迎纠正,另外概念上有问题也欢迎纠正。