介绍PySpark访问Hbase的两种方法,一种是通过newAPIHadoopRDD,读取Hbase为RDD,并转成DataFrame,另一种是在Hive里建立Hbase的外部表,然后通过Spark Sql读取
一、通过newAPIHadoopRDD读取
#spark连接hbase,读取RDD数据
spark = SparkSession.builder.master("yarn-client").appName("hbase_test").getOrCreate()
hbaseconf = {"hbase.zookeeper.quorum":'10.18.105.15',"hbase.mapreduce.inputtable":"table_name",
"hbase.mapreduce.scan.row.start":"***", "hbase.mapreduce.scan.row.stop":"***"}
keyConv = "org.apache.spark.examples.pythonconverters.ImmutableBytesWritableToStringConverter"
valueConv = "org.apache.spark.examples.pythonconverters.HBaseResultToStringConverter"
hbase_rdd = spark.sparkContext.newAPIHadoopRDD(\
"org.apache.hadoop.hbase.mapreduce.TableInputFormat",\
"org.apache.hadoop.hbase.io.ImmutableBytesWritable",\
"org.apache.hadoop.hbase.client.Result",\
keyConverter=keyConv, valueConverter=valueConv, conf=hbaseconf)
#从每列的dict中提取列名和取值,组成dict
def call_transfor(y1):
y2 = [json.loads(i) for i in y1]
fdc={}
for i in y2:
colname = i['qualifier']
value = i['value']
fdc[colname] = value
return fdc
#将hbase RDD转换为DataFrame
def rdd_to_df(hbase_rdd):
#同一个RowKey对应的列之间是用\n分割,进行split,split后每列是个dict
fdc_split = hbase_rdd.map(lambda x:(x[0],x[1].split('\n')))
#提取列名和取值
fdc_cols = fdc_split.map(lambda x:(x[0],call_transfor(x[1])))
colnames = ['row_key'] + fdc_cols.map(lambda x:[i for i in x[1]]).take(1)[0]
fdc_dataframe = fdc_cols.map(lambda x:[x[0]]+[x[1][i] for i in x[1]]).toDF(colnames)
return fdc_dataframe
#数据转换
fdc_data = rdd_to_df(hbase_rdd)
二、通过Spark访问Hbase的Hive外部表
前提是你已经可以通过spark-sql读取hive的数据了,然后进行如下配置。
1.拷贝如下jar包到${spark_home}/jars(spark2.0之前是${spark_home}/lib):
2.将hbase的配置文件 hbase-site.xml 拷贝到${spark_home}/conf目录下。
#建立Hbase的Hive外部表
spark.sql('''
create external table hbase_hive_external_table( key string, col map
STORED BY "org.apache.hadoop.hive.hbase.HBaseStorageHandler"
WITH SERDEPROPERTIES ("hbase.columns.mapping" = "t:")
TBLPROPERTIES("hbase.table.name" = "hive_hbase_test"
''')
#spark-sql直接读取
spark.sql("select * from hbase_hive_external_table")
#先落地成Parquet文件再读取,速度会快一些
spark.sql("create table temp.hbase_hive_parquet stored as parquet as select * from hbase_hive_external_table")
spark.read.parquet("/user/hive/warehouse/temp.db/hbase_hive_parquet")