# 使用 Kudu 开发应用程序
原文链接 : [http://kudu.apache.org/docs/developing.html](http://kudu.apache.org/docs/developing.html)
译文链接 : [http://cwiki.apachecn.org/pages/viewpage.action?pageId=10813629](http://cwiki.apachecn.org/pages/viewpage.action?pageId=10813629)
贡献者 : [小瑶](/display/~chenyao) [ApacheCN](/display/~apachecn) [Apache中文网](/display/~apachechina)
## 使用 Kudu 开发应用程序
**Kudu **提供 **C ++**,**Java** 和 **Python** 客户端 **API** 以及参考示例来说明它们的用途。
注意
不支持使用服务器端或专用接口,不属于公共 **API** 的接口没有稳定性保证。
## 查看 API 文档
### C++ API 文档
您可以在线查看 **C ++** 客户端 **API** 文档。或者,在从源代码构建 **Kudu** 后,您还可以另外构建 **doxygen** 目标(例如,如果使用 **make** ,则运行 **make doxygen** ),并通过在您最喜欢的 **Web** 中打开 **docs/doxygen/client_api/html/index.html** 文件来使用本地生成的 **API** 文档浏览器。
重要
为了构建 **doxygen** 目标,有必要在您的构建机器上安装带有 **Dot( graphviz )**支持的 **doxygen** 。如果您从源代码构建 **Kudu** 后安装了 **doxygen** ,则需要再次运行 **cmake** 以获取 **doxygen** 位置并生成适当的目标。
### Java API 文档
您可以在线查看[ **Java API** 文档](http://kudu.apache.org/apidocs/index.html) 。或者,在构建 [**Java** 客户端](/pages/viewpage.action?pageId=10813629)之后,**Java API** 文档可以在 **java/kudu-client/target/apidocs/index.html** 中找到。
## 工作实例
[**kudu** 示例](https://github.com/cloudera/kudu-examples) **Github** 仓库中提供了几个示例应用程序。每个示例包括一个自述文件,显示如何编译和运行它。这些例子说明了 **Kudu** **API** 的正确使用,以及如何设置虚拟机来运行 **Kudu** 。以下列表包括今天可用的一些示例。检查存储库本身,以防此列表过期。
**java/java-example**
连接到 **Kudu** 实例的简单 **Java** 应用程序创建一个表,向其中写入数据,然后丢弃该表。
**java/collectl**
侦听 **TCP** 套接字的小型 **Java** 应用程序,用于与 **Collectl** 有线协议相对应的时间序列数据。常用的 **collectl** 工具可用于将示例数据发送到服务器。
**java/insert-loadgen**
生成随机插入负载的 **Java** 应用程序。
**python/dstat-kudu**
一个示例程序,显示如何使用 **Kudu Python API** 将数据加载到由外部程序生成的新的/现有的 **Kudu** 表中, **dstat** 在这种情况下。
**python/graphite-kudu**
使用 **graphite-web** ( 石墨网 ) 与 **Kudu** 作为后端的实验插件。
**demo-vm-setup**
脚本下载并运行带有 **Kudu** 的 **VirtualBox** 虚拟机已安装。有关详细信息,请参阅 [快速入门](/pages/viewpage.action?pageId=10813610) 。
这些例子应该是您自己的 **Kudu** 应用程序和集成的有用起点。
### Maven Artifacts ( Maven 工件 )
以下 **Maven <dependency>** 元素对于 **Apache Kudu** 公开版本(从**1.0.0** 开始)是有效的:
```
<dependency>
<groupId>org.apache.kudu</groupId>
<artifactId>kudu-client</artifactId>
<version>1.1.0</version>
</dependency>
```
**Java** 客户端和各种 **Java** 集成(例如 **Spark** , **Flume** )的便利二进制文件现在也可以通过[ **ASF Maven** 存储库](http://repository.apache.org/) 和[ **Maven Central** 存储库](https://mvnrepository.com/artifact/org.apache.kudu)获得。
## Impala命令使用 Kudu 的例子
请参阅 [使用 **Impala** 与 **Kudu**](/pages/viewpage.action?pageId=10813620) 进行有关使用 **Kudu** 安装和使用 **Impala** 的指导,其中包括几个 **impala-shell** 示例。
## Kudu 与 Spark 集成
**Kudu** 从 **1.0.0** 版开始,通过 **Data Source API** 与 **Spark** 集成。使用 **--packages** 选项包括 **kudu-spark** 依赖关系:
如果使用 **Spark** 与 **Scala 2.10** ,请使用 **kudu-spark_2.10** 插件:
```
spark-shell --packages org.apache.kudu:kudu-spark_2.10:1.1.0
```
如果在 **Scala 2.11** 中使用 **Spark 2** ,请使用 **kudu-spark2_2.11** 插件:
```
spark-shell --packages org.apache.kudu:kudu-spark2_2.11:1.1.0
```
然后导入 **kudu-spark** 并创建一个数据框:
```
import org.apache.kudu.spark.kudu._
import org.apache.kudu.client._
import collection.JavaConverters._
// Read a table from Kudu
val df = sqlContext.read.options(Map("kudu.master" -> "kudu.master:7051","kudu.table" -> "kudu_table")).kudu
// Query using the Spark API...
df.select("id").filter("id" >= 5).show()
// ...or register a temporary table and use SQL
df.registerTempTable("kudu_table")
val filteredDF = sqlContext.sql("select id from kudu_table where id >= 5").show()
// Use KuduContext to create, delete, or write to Kudu tables
val kuduContext = new KuduContext("kudu.master:7051", sqlContext.sparkContext)
// Create a new Kudu table from a dataframe schema
// NB: No rows from the dataframe are inserted into the table
kuduContext.createTable(
"test_table", df.schema, Seq("key"),
new CreateTableOptions()
.setNumReplicas(1)
.addHashPartitions(List("key").asJava, 3))
// Insert data
kuduContext.insertRows(df, "test_table")
// Delete data
kuduContext.deleteRows(filteredDF, "test_table")
// Upsert data
kuduContext.upsertRows(df, "test_table")
// Update data
val alteredDF = df.select("id", $"count" + 1)
kuduContext.updateRows(filteredRows, "test_table"
// Data can also be inserted into the Kudu table using the data source, though the methods on KuduContext are preferred
// NB: The default is to upsert rows; to perform standard inserts instead, set operation = insert in the options map
// NB: Only mode Append is supported
df.write.options(Map("kudu.master"-> "kudu.master:7051", "kudu.table"-> "test_table")).mode("append").kudu
// Check for the existence of a Kudu table
kuduContext.tableExists("another_table")
// Delete a Kudu table
kuduContext.deleteTable("unwanted_table")
<> and OR predicates are not pushed to Kudu, and instead will be evaluated by the Spark task. Only LIKE predicates with a suffix wildcard are pushed to Kudu, meaning that LIKE "FOO%" is pushed down but LIKE "FOO%BAR" isn’t.
```
### Spark 集成已知问题和限制
* 注册为临时表时,必须为具有大写字母或非 **ASCII** 字符的名称的 **Kudu** 表分配备用名称。
* 具有包含大写字母或非 **ASCII** 字符的列名称的 **Kudu** 表可能不与 **SparkSQL** 一起使用。 **Columns **可能在 **Kudu** 更名为解决这个问题。
* **<>** 和 **OR** 谓词不被推送到 **Kudu** ,而是将在 **Spark** 的evaluate过程中执行, 只有具有后缀通配符的 **LIKE** 谓词才被推送到 **Kudu** 执行,这意味着 **LIKE“FOO%”**语句被下推到**Kudu**,而 **“FOO%BAR”** 这样的语句不会。
* **Kudu** 不支持 **Spark SQL** 支持的所有类型,例如 **Date** , **Decimal** 和复杂类型。
* **Kudu** 表只能在 **SparkSQL** 中注册为临时表。 可能不会使用 **HiveContext** 查询 **Kudu** 表。
## Kudu Python 客户端
**Kudu Python** 客户端为 **C ++** 客户端 API 提供了一个 **Python** 友好的界面。 下面的示例演示了如何使用部分 **Python** 客户端。
```
import kudu
from kudu.client import Partitioning
from datetime import datetime
# Connect to Kudu master server
client = kudu.connect(host='kudu.master', port=7051)
# Define a schema for a new table
builder = kudu.schema_builder()
builder.add_column('key').type(kudu.int64).nullable(False).primary_key()
builder.add_column('ts_val', type_=kudu.unixtime_micros, nullable=False, compression='lz4')
schema = builder.build()
# Define partitioning schema
partitioning = Partitioning().add_hash_partitions(column_names=['key'], num_buckets=3)
# Create new table
client.create_table('python-example', schema, partitioning)
# Open a table
table = client.table('python-example')
# Create a new session so that we can apply write operations
session = client.new_session()
# Insert a row
op = table.new_insert({'key': 1, 'ts_val': datetime.utcnow()})
session.apply(op)
# Upsert a row
op = table.new_upsert({'key': 2, 'ts_val': "2016-01-01T00:00:00.000000"})
session.apply(op)
# Updating a row
op = table.new_update({'key': 1, 'ts_val': ("2017-01-01", "%Y-%m-%d")})
session.apply(op)
# Delete a row
op = table.new_delete({'key': 2})
session.apply(op)
# Flush write operations, if failures occur, capture print them.
try:
session.flush()
except kudu.KuduBadStatus as e:
print(session.get_pending_errors())
# Create a scanner and add a predicate
scanner = table.scanner()
scanner.add_predicate(table['ts_val'] == datetime(2017, 1, 1))
# Open Scanner and read all tuples
# Note: This doesn't scale for large scans
result = scanner.open().read_all_tuples()
```
## 与 MapReduce , YARN 和其他框架集成
**Kudu** 旨在与 **Hadoop** 生态系统中的 **MapReduce** , **YARN** , **Spark** 和其他框架集成。 请参阅 **[RowCounter.java](https://github.com/apache/kudu/blob/master/java/kudu-client-tools/src/main/java/org/apache/kudu/mapreduce/tools/RowCounter.java)** 和** [ImportCsv.java](https://github.com/apache/kudu/blob/master/java/kudu-client-tools/src/main/java/org/apache/kudu/mapreduce/tools/ImportCsv.java)** ,了解可以对自己的集成进行建模的示例。 请继续关注未来使用 **YARN** 和 **Spark** 的更多示例。