在資料爆發式增長的時代,記錄資料變化和演變,**內在規律並運用到生產實踐中,驅動業務的增長成為這個時代主旋律。本文就如何記錄資料變化,處理資料變化談談自己的理解
所要更改的屬性,始終保持最新值,即覆蓋重寫,但是該技術破壞了歷史情況。需要借助其他的方式才能進行處理,這點我們在本文下面會講到。
當發生屬性的變化時候,不修改原來的行,而是增加新的記錄行。所以原先表的設計時候,主鍵更加需要具備一般意義的型別,因為會出現多行共同描述乙個物件,共同描述乙個物件的相同成員(屬性)。採用這種方式最少需要三個額外的列:行有效的時間戳,行失效的時間戳,當前行的標識。
對原先修改的值,不變。對新變化的值,採用新增一列,來記錄。這種運用場合有限,eg,freeschema型別的資料庫,且變化頻度有限且低的場合。
增加新的表,用來記錄變化。這種一般用在源表資料量大,且屬性變化較快的表,新錶要維護乙個屬性和源表的對映。優點是對源表無侵入性修改,對寫是友好的。而查詢需要連表查詢,會有一定的影響
增加新的表,用來記錄變化,同時對原表的需要修改的記錄進行重寫,即新錶純粹就是用來記錄變化的歷史,優點是對源表查詢是只需要查詢源表,寫入速度會有一定影響
在變化資料的儲存
一節中,我們談到了對變化資料儲存。從方式2-5都可以對歷史進行捕獲。如果乙個系統對原先變化資料有處理需求,在系統設計之初可以參考上面的方式。從源頭開始設計會對後面的資料處理帶來極大便利。如果是現有系統,且設計之初沒有考慮對變化資料的處理。可以借助下面幾種方式。
在1.1的基礎之上,增加乙個行變化的有效標記位。讓下游系統可以進行捕獲。優點需要修改的地方較為簡單:1.對資料庫物理設計調整,2.現有應用系統的業務邏輯進行簡單調整
update source_table
set update_col=col_value,valid=1
where pk_col=pk_col_value
需要考慮的地方:
原系統相同記錄倆次更新間隙,下游系統沒有及時感知並捕獲,更新操作如何處理? 從盡量不對原先業務系統產生影響的設計原則考慮,更新操作正常進行,但是對於資料採集可能會丟失一部分的資料
業務庫寫許可權,開放給下游業務無關的系統(資料採集系統,為避免架構上的複雜性以及後期應對變化的擴充套件效能,一般設計為業務無關),會帶來侵入式風險,即修改了標記位以外的列。
從系統效能上考慮,下游系統去掃標記位,在現有rdbms系統上沒有對資料庫效能產生影響的設計。現有基本可行的方式,1. 建立b+/-tree索引,但是對於標記位值重複量大的不是乙個友好設計。2. 建立bit-map索引。bit-map最適合重複值多的場景,但是會極大影響寫入效能,適用於表修改頻率不多的情況。3. 脫離就技術而論技術角度看,著眼與實際業務結合,這種沒有普適原則,需要對每個業務系統進行分析,但是這違背了採集系統,需要適應並儘量減少接入成本的業務無關的原則。如果資料產生之初,接入之初都很難,那系統有極大的夭折可能性。好像生小孩也是這樣?
2.2.1 oracle
方式1:oracle作為乙個商用資料提供了,完整系統描述的元資料。通過讀取元資料表來記錄來查詢所有的更改的操作。通過下面的語句
-- sql_fulltext操作的sql語句
-- command_type 命令型別,2-insert,6-update,7-delete
-- rows_processed 影響的行數
-- last_load_time 最近一次執行的時間
-- first_load_time 第一次執行的時間
select sql_fulltext,disk_reads,buffer_gets,rows_processed,command_type,cpu_time,user_io_wait_time,
physical_read_requests,physical_read_bytes,last_load_time from v$sql
where sql_fulltext like '%tbl_test%' and command_type in(2,6,7)and rows_processed>0
ref:oracle docs
方式2:利用表的觸發器,通過每次寫且觸發觸發器的動作完成更新動作的識別和解析。現有開源框架-databus,oracle的解析原理就是採用這種方式
2.2.2 sqlsever
sqlserver也有類似的表結構sys.dm_exec_sql_text
ref:sql server docs
oracle方式1,sqlserver的方式,利用這些方式的優點,1.完全重用現有技術,利用jdbc,select查詢操作,就可以找到所有修改。2.保證庫內擴充套件性同時,不對系統現有設計產生影響。因為對所有的表更新操作,都在v$sql中都可以找到,不需在接入資料時,對單個表進行重新設計和業務處理,所有更新查詢都使用一套sql。缺點:1.需要不斷輪訓v$sql ,延遲在秒,分鐘級別。看系統設定。2. 需要v$sql的許可權,一般是管理員許可權。 oracle 方式2的缺點,觸發器使用會增加系統的開銷,影響系統的吞吐量,特別是在頻繁的更新(update,insert,delete)情況。觸發器使用需要對錶做謹慎評估
2.3.1 簡單解析型-mysql
借助binlog的明文日誌,需要設定下面倆個選項
set binlog_rows_query_log_events=1
set binlog_format=row
在my.cnf中配置
log-bin=binlog的目錄和binlog檔案字首
所有更新的操作都會明文列印到log-bin設定的檔案下。借助kafka connector-filesystem source 將binlog明文sql傳輸到kafka中。
2.3.2 複雜解析型-mysql
通過對資料庫日誌的挖掘,完成解析,現有的開源框架openreplicator,databus,mysql的解析就是借助openreplicator,完成對binlog的解析。
上述倆種方式的共同優點,只需要要開啟binlog列印,對系統負擔小,下游程式不會對現有系統產生衝擊此外,使用簡單型日誌,還有解析明文sql,由於採用sql的通用標準,解析程式具有較好的通用性,對於後期維護負擔小,而複雜解析型sql,隨著軟體版本的公升級binlog的解析也需要不斷公升級,後續維護成本較高
在變化資料的捕獲
一節中,我們對事前沒有考慮儲存歷史變更的情況,如何捕獲變化資料做了分享。綜合上面幾種方式的優缺點,
table schema:fino_id,sql_fulltext,exec_time,command_type
fino_id:auto-inc
sql_fulltext:執行更新的sql指令碼
exec_time:執行時間
command_type:sql語句型別
針對mysql,則較為簡單,在binlog本地磁碟部署kafka connector localfilesource,將binlog日誌傳輸到kafka。
小結:採用這種方案主要是基於以下幾點考慮:
基於客戶方敏感的資料庫許可權要求,和客戶方對關係型資料庫運維技術沉澱,保證資料源頭的穩定性
上下游系統弱依賴,即使下游系統出現問題,源頭的資料還是存在,和持續生產的。實現源頭資料較強容錯
可以做到較強的擴充套件性,在庫內以及不同資料庫產品(特指sql server和oracle)不用針對單個表,做單獨業務設計。降低接入成本。
資料的etl可以放到資料平台進行統一清洗和挖掘。
history_log,採用iot表,讀寫請求都轉化為順序讀寫,實現了較高的讀寫效能
資料採集系統從站設計
軟體設計 程式的說明 本程式為從站程式。完成 ad,接受命令,並傳送資料等功能,以及實現主從式 485協議 見rs485 中的從站功能。1.該程式有以下功能 初始化,ad,定時器,串列埠接受,串列埠傳送 2.主程式完成初始化。之後不斷查詢是否有接受資料,並作出相應處理 啟動 ad,傳送資料,狀態等。...
關聯式資料庫(RDBMS)和NoSQL的比較
現在主流的sql關聯式資料庫有 oracle sql server mysql nosql資料庫有bigtable hbase cassandra db couchdb mongodb和redis等。sql月nosql的主要區別有 關聯式資料庫用表來儲存資料,nosql資料庫則用json 鍵值對 文...
初始大資料 02 日誌採集大資料和爬蟲採集大資料
此圖借鑑 關鍵字 從整體上描述 agent 中 sources sinks channels 所涉及的元件 詳細指定agent中每個sources,sinks 和channels的具體實現 通過 channel 將 source 與 sink 連線起來。啟動 agent 的 shell 操作 網路爬...