kudu介紹
Kudu是運作在hadoop平台上的列式存儲系統,擁有Hadoop生态系統應用的常見技術特性,運作在一般的商用硬體上,支援水準擴充,高可用。
kudu的優勢
1)一個table由多個tablet組成,對分區檢視、擴容和資料高可用支援非常好
2)支援update和upsert操作。
3)與presto內建或spark內建後(dataframe)可通過标準的sql操作,使用起來很友善
4)可與spark系統內建
kudu的劣勢
1)隻有主鍵可以設定range分區,且隻能由一個主鍵,也就是一個表隻能有一個字段range分區,且該字段必須是主鍵。
2)如果是pyspark連接配接kudu,則不能對kudu進行額外的操作;而scala的spark可以調用kudu本身的庫,支援kudu的各種文法。
3)kudu的shell用戶端不提供表schema檢視。如果你不通過imapla連接配接kudu,且想要檢視表的中繼資料資訊,需要用spark加載資料為dataframe,通過檢視dataframe的schema檢視表的中繼資料資訊。
3)kudu的shell用戶端不提供表内容檢視。如果你想要表的據資訊,要麼自己寫腳本,要麼通過spark、imapla檢視。
4)如果使用range 分區需要手動添加分區。假設id為分區字段,需要手動設定第一個分區為1-30.第二個分區為30-60等等
問題描述
在項目中有個功能是外導使用者群,每次導入重複的記錄數,總是顯示重複記錄數為0。因為我們是将導入的檔案内容先存儲在group_input表中,表結構如下
CREATE TABLE group_input (
l_date varchar commen ‘日期’,
file_id varchar ‘導入檔案id’,
id_type varchar ‘id類型’,
id_str varchar ‘id值’,
super_id varchar ‘唯一id’
)
WITH (
column_design = ‘{“l_date”:{“key”:true,“nullable”:false,“encoding”:“AUTO_ENCODING”,“compression”:“DEFAULT_COMPRESSION”},“file_id”:{“key”:true,“nullable”:false,“encoding”:“AUTO_ENCODING”,“compression”:“DEFAULT_COMPRESSION”},“id_type”:{“key”:true,“nullable”:false,“encoding”:“AUTO_ENCODING”,“compression”:“DEFAULT_COMPRESSION”},“id_str”:{“key”:true,“nullable”:false,“encoding”:“AUTO_ENCODING”,“compression”:“DEFAULT_COMPRESSION”},“super_id”:{“key”:false,“nullable”:true,“encoding”:“AUTO_ENCODING”,“compression”:“DEFAULT_COMPRESSION”}}’,
partition_design = ‘{“hash”:[{“columns”:[“file_id”,“id_type”,“id_str”],“buckets”:3}],“range”:null}’
);
我們設計是以l_date,id_str,id_type,file_id作為聯合主鍵,現在使用java API操作kudu,往表裡面添加10條重複資料。
public static void main(String[] args) throws KuduException {
String kuduAddress = "nffapp01:7051,nffapp02:7051,nffdata02:7051";
KuduClient kuduClient = new KuduClient.KuduClientBuilder(kuduAddress).build();
//建立表
//建立kudu表字段
LinkedList<ColumnSchema> columnSchemas = new LinkedList<>();
columnSchemas.add(KuduUtil.newColumn("l_date", Type.STRING,true));
columnSchemas.add(KuduUtil.newColumn("file_id",Type.INT32,true));
columnSchemas.add(KuduUtil.newColumn("id_type",Type.STRING,true));
columnSchemas.add(KuduUtil.newColumn("id_str",Type.STRING,true));
columnSchemas.add(KuduUtil.newColumn("super_id",Type.STRING,false));
//建立schema
Schema schema = new Schema(columnSchemas);
//建立表提供的所有選項
CreateTableOptions createTableOptions = new CreateTableOptions();
//設定副本數
createTableOptions.setNumReplicas(1);
//設定範圍分區的規則
LinkedList<String> list = new LinkedList<String>();
list.add("l_date");
//設定hash分區
createTableOptions.addHashPartitions(list,5);
kuduClient.createTable("group_input",schema,createTableOptions);
//向表内插入新資料
KuduTable table = kuduClient.openTable("group_input");
KuduSession session = kuduClient.newSession();
session.setTimeoutMillis(60000);
for (int i = 0; i < 10; i++) {
logger.info("----------------insert "+i+"---------------");
Insert insert = table.newInsert();
PartialRow row = insert.getRow();
row.addString(0, "2019-08-01");
row.addInt(1,20);
row.addString(2, "20"+i);
row.addString(3, "18664301061");
row.addString(4, "super_id:9980767");
session.apply(insert);
}
kuduClient.close();
}
}
獲得的結果,根據id_type可以看出插入了第一條記錄後其他記錄都未插入。

當修改id_type和file_id值的時候,則資料可以全部插入,結果如圖
總結
産品在設計之時沒有考慮到kudu表主鍵的唯一性。當同一個檔案中包含相同的記錄時,隻能導入一條記錄。為了滿足項目需要,隻能修改統計規則,總記錄條數=導入成功數+導入失敗數+重複數,這樣的話就重複數=成功重複數+失敗重複數