背景
Apache Kudu 是 Cloudera 贡献的开源项目,主要特点是:
- Streamlined Architecture
- Faster Analytics
- Open for Contributions
Kudu 是在 HBase 出现之后,根据 Hbase 的思想开发的。
HBase 一般将数据持久化在 HDFS 中,使用 HDFS 的数据一致性;而 Kudu 是存储在本地,通过 raft 协议来保证强一致和高可靠性。
Kudu 的设计目标是快速分析,除了和 Hbase 一样支持随机读写外,在数据扫描(Scan)的性能比 Hbase 要好,适合 OLAP 场景。
另外,Kudu 核心模块由 C++ 开发,没有 gc 风险;而 Hbase 由 Java 开发,内存紧张时有 gc 风险。
详细对比见参考 1。
与 Parquet, Hbase 比较
整理自 The Columnar Era: Leveraging Parquet, Arrow and Kudu for High-Performance Analytics
分析(快速 Scan) | 随机读写 | ||
---|---|---|---|
Parquet | 最好 | 最差 | |
KUDU | 较好 | 较好 | |
HBase | 最差 | 最好 |
安装
Kudu 可以单独安装,也可以在安装 CDH 时做为一个组件自动安装。
这里单独安装仅仅为了测试,生产环境中还是使用的 CDH 安装。
单独安装方法,来自于参考官方文档。
另外,本文单独安装方法安装的是 kudu 1.4。官方最新的版本是 kudu 1.7。
RHEL 7
增加源
wget http://archive.cloudera.com/kudu/redhat/7/x86_64/kudu/cloudera-kudu.repo
保存到文件夹 /etc/yum.repos.d/
下
可以使用阿里云的镜像,见 http://mirrors.aliyun.com/
安装源
sudo yum install kudu # Base Kudu files sudo yum install kudu-master # Kudu master init.d service script and default configuration sudo yum install kudu-tserver # Kudu tablet server init.d service script and default configuration sudo yum install kudu-client0 # Kudu C++ client shared library sudo yum install kudu-client-devel # Kudu C++ client SDK
启动服务
[root@localhost fw]# /etc/init.d/kudu-tserver start Started Kudu Tablet Server (kudu-tserver): [ 确定 ] [root@localhost fw]# /etc/init.d/kudu-master start Started Kudu Master Server (kudu-master): [ 确定 ]
确认进程 kudu-tserver
和 kudu-master
都存在
- Master:
kudu-master
的页面为http://localhost:8051
- Tablet Server:
kudu-tserver
的页面为http://localhost:8050
如果远程连接不上的话,确认一下 linux 的防火墙是不是屏蔽了对应的请求。
配置文件
/etc/kudu/conf/master.gflagfile /etc/kudu/conf/tserver.gflagfile
一般不用修改
但是如果是单机测试的话,修改一下最小分片数到 1 吧。
分别修改这两个配置文件,增加:
--unlock_unsafe_flags=true --allow_unsafe_replication_factor=true --default_num_replicas=1 --rpc_negotiation_timeout_ms=9000
然后重启两个服务。
Python 使用
由简单到复杂,先来看 python 的使用吧。
具体参考了官方 kudu-python 示例和 pydoc kudu 帮助手册。
安装 kudu-python
先安装 pip,如果已经有了请略过
sudo yum -y install epel-release python2-pip python-devel
pip 安装 kudu-python
## 准备活动 pip install --upgrade pip pip install --upgrade setuptools ## 安装包. 对于 kudu1.4,要选择1.2.0的kudu-python pip install Cython kudu-python==1.2.0
查看所有可以安装的版本:
指定个不存在的版本,就会提示出所有可选的版本。
pip install kudu-python==99.99.99 Collecting kudu-python==99.99.99 Could not find a version that satisfies the requirement kudu-python==99.99.99 (from versions: 0.1.0, 0.1.1, 0.2.0, 0.3.0, 1.1.0, 1.2.0, 1.7.0) No matching distribution found for kudu-python==99.99.99
使用
连接
>>> import kudu >>> client = kudu.Client("127.0.0.1:7051")
查看表
>>> client.list_tables() ['java_sample-1527939906616', 'java_sample-1527939874474', 'java_sample-1527938481750', 'java_sample-1527938216058']
删除表
>>> client.delete_table('java_sample-1527939906616') >>> client.list_tables() ['java_sample-1527939874474', 'java_sample-1527938481750', 'java_sample-1527938216058']
创建表
创建 schema
>>> builder = kudu.schema_builder() >>> builder.add_column('key', kudu.int32, nullable=False) >>> builder.add_column('value', kudu.string, nullable=False).compression('lz4') >>> builder.set_primary_keys(['key']) >>> schema = builder.build()
创建 partition
>>> from kudu.client import Partitioning >>> partitioning=Partitioning().add_hash_partitions(['key'], 2)
创建表
>>> client.create_table('table_demo',schema,partitioning)
查看表结构
>>> table = client.table('java_sample-1527939874474') >>> table.schema kudu.Schema { key int32 NOT NULL value string NOT NULL PRIMARY KEY (key) }
查看表内容
>>> scanner = table.scanner() >>> scanner.open() <kudu.client.Scanner object at 0x7fb7f78982d0> >>> tuples = scanner.read_all_tuples() >>> tuples [(0, 'value 0'), (1, 'value 1'), (2, 'value 2')]
插入数据到表
>>> session = client.new_session() >>> op = table.new_insert() >>> op['key']=3 >>> op['value']='value 3' >>> session.apply(op) >>> session.flush()
验证插入成功
>>> scanner = table.scanner() >>> scanner.open() <kudu.client.Scanner object at 0x7fb7f7898960> >>> scanner.read_all_tuples() [(0, 'value 0'), (1, 'value 1'), (2, 'value 2'), (3, 'value 3')]
其它操作
其它操作有:
- new_delete: 删除数据
- new_update: 更新数据
- new_upsert: 如果存在则更新数据,不存在则插入数据
- rename: 更改表名
Java 使用
这里 java 依赖了 1.4 的 kudu-client,示例代码见 github。
Java 依赖
<dependencies> <dependency> <groupId>org.apache.kudu</groupId> <artifactId>kudu-client</artifactId> <version>1.4.0</version> </dependency> </dependencies>
示例代码
演示了创建表,写入数据,扫描数据,和删除表的过程。
代码来自 github
import java.util.ArrayList; import java.util.List; import org.apache.kudu.ColumnSchema; import org.apache.kudu.Schema; import org.apache.kudu.Type; import org.apache.kudu.client.CreateTableOptions; import org.apache.kudu.client.Insert; import org.apache.kudu.client.KuduClient; import org.apache.kudu.client.KuduScanner; import org.apache.kudu.client.KuduSession; import org.apache.kudu.client.KuduTable; import org.apache.kudu.client.PartialRow; import org.apache.kudu.client.RowResult; import org.apache.kudu.client.RowResultIterator; public class Sample { private static final String KUDU_MASTER = System.getProperty("kuduMaster", "192.168.199.137:7051"); public static void main(String[] args) { System.out.println("-----------------------------------------------"); System.out.println("Will try to connect to Kudu master at " + KUDU_MASTER); System.out.println("Run with -DkuduMaster=myHost:port to override."); System.out.println("-----------------------------------------------"); String tableName = "java_sample-" + System.currentTimeMillis(); KuduClient client = new KuduClient.KuduClientBuilder(KUDU_MASTER).build(); try { // 建表 List<ColumnSchema> columns = new ArrayList(2); columns.add(new ColumnSchema.ColumnSchemaBuilder("key", Type.INT32).key(true).build()); columns.add(new ColumnSchema.ColumnSchemaBuilder("value", Type.STRING).build()); List<String> rangeKeys = new ArrayList<>(); rangeKeys.add("key"); Schema schema = new Schema(columns); client.createTable(tableName, schema, new CreateTableOptions().setRangePartitionColumns(rangeKeys)); // 插入数据 KuduTable table = client.openTable(tableName); KuduSession session = client.newSession(); for (int i = 0; i < 3; i++) { Insert insert = table.newInsert(); PartialRow row = insert.getRow(); row.addInt(0, i); row.addString(1, "value " + i); session.apply(insert); } // 查询数据 List<String> projectColumns = new ArrayList<>(1); projectColumns.add("value"); KuduScanner scanner = client.newScannerBuilder(table).setProjectedColumnNames(projectColumns).build(); while (scanner.hasMoreRows()) { RowResultIterator results = scanner.nextRows(); while (results.hasNext()) { RowResult result = results.next(); System.out.println(result.getString(0)); } } } catch (Exception e) { e.printStackTrace(); } finally { try { // 删除表 client.deleteTable(tableName); } catch (Exception e) { e.printStackTrace(); } finally { try { client.shutdown(); } catch (Exception e) { e.printStackTrace(); } } } } }
运行结果
----------------------------------------------- Will try to connect to Kudu master at 192.168.199.137:7051 Run with -DkuduMaster=myHost:port to override. ----------------------------------------------- [New I/O worker #2] WARN org.apache.kudu.util.NetUtil - Slow DNS lookup! Resolved IP of `localhost' to localhost/127.0.0.1 in 3168448ns value 0 value 1 value 2
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于