一般而言,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))

以上代码没有测试,如有问题欢迎纠正,另外概念上有问题也欢迎纠正。