postgresql資料定時轉存mongodb方案

木头左發表於2024-04-20
  • 案例背景

很多事件記錄在最初一段時間讀寫比較頻繁,儲存在postgresql比較合適,後期資料量變大,且僅作為歷史記錄查詢,更適合儲存在mongodb中,可能需要定期將postgresql中的資料轉存到mongodb。

  • 案例分析

postgresql資料定時轉存mongodb,可以採用jdbc方式將postgresql讀入記憶體,對每條資料進行解析,轉成json格式,按mongodb的語法寫入資料庫。這種方法弊端是,需要對各表建立實體物件,依次解析,或者用更不優雅的方式拼接字串,整個方案擴充套件性低,可維護性差。因此,我們採用kettle來完成資料的postgresql讀取和mongodb插入指令碼編寫,並在java工程中進行kettle呼叫。

  • 實現方案

1****、transformation

採用transformation完成針對資料的基礎轉換,執行SQL和資料postgresql讀取和mongodb插入等,job則設定定時任務呼叫transformation,完成對整個工作流程的控制。

1、表輸入

表輸入查詢要轉存到mongodb中的資料記錄,提供資料來源。

其中資料庫連線,要編輯資料庫連線型別、IP、埠、密碼、資料庫名等資訊。

2、json輸出

json輸出中操作選擇Output value,json條目名稱輸入json名稱,輸出值也選擇Output value,欄位中選擇需要插入的欄位。

3、插入mongodb

在Big Data中選擇MongoDB Output外掛,在Configure connection中輸入連線資訊。

在Output options中設定插入時的模式

Truncate:插入資料之前先把集合裡的所有資料刪除,此模式慎用,僅用於首次全量同步;

Update:更新資料,存在則修改,不存在不操作。

upsert:更新新增,找到匹配項則修改,找不到匹配項則新增。

如果設定了Update模式,在Mongo document fields中需要選擇某一欄位的Modifier operation設為N/A,其他欄位設為$set,表示將該欄位作為更新標準,當該欄位值存在時,其他欄位更新。

可以在Create/drop indexes中建立索引。

注:mongodb外掛可能遇到報錯:java.lang.NoClassDefFoundError: javax/crypto/spec/PBEKeySpec

在data-integration\system\karaf\etc\config.properties中org.osgi.framework.bootdelegation引數新增“,javax.crypto,javax.crypto.*”,保證能正常載入加解密相關類。

2****、job

在start中選擇合適的時間間隔,以圖為例10分鐘執行一次。

將之前的transformation新增至轉換中

3****、java工程呼叫

1、匯入jar包

將kettle基礎的jar包匯入工程,另外將mongodb驅動mongo-java-driver-2.13.0.jar也匯入工程中

2、匯入外掛

將\data-integration\system\karaf\system\pentaho 目錄下的外掛資料夾pentaho-mongo-utils和pentaho-mongodb-plugin匯入工程根目錄

3、傳入kettle job指令碼路徑,如果有需要傳入指令碼中的引數,在params中設定入參:
public static void main(String[] args) throws IOException {

String[] params = { "101", "content", "" };

runJob(params,"E:\\dict_data\pgToMongodb.kjb");

}

4、將需要的引數在job中設定,設定日誌級別,ERROR錯誤日誌,BASIC基礎日誌,ROWLEVEL行級日誌,環境初始化並執行job:

public static boolean runJob(String[] params, String jobPath) { try { KettleEnvironment.init(); // jobPath是Job指令碼的路徑及名稱 JobMeta jobMeta = new JobMeta(jobPath, null); Job job = new Job(null, jobMeta); job.setLogLevel(LogLevel.ROWLEVEL); job.start(); job.waitUntilFinished(); // 向Job 指令碼傳遞引數,指令碼中獲取引數值:${引數名} job.setLogLevel(LogLevel.ROWLEVEL); job.start(); job.waitUntilFinished(); if (job.getErrors() > 0) { return false; } else { return true; } } catch (Exception e) { e.printStackTrace(); } return false; }

  • 結束語

1、 kettle中postgresql資料轉存mongodb,單執行緒任務Truncate模式下每秒6000-11000條資料,Update模式下每秒600-1000條資料,相差10倍效率,初次全量同步時儘量採用Truncate模式。

2、要控制合理的同步時間間隔,避免過於頻繁導致資料傳輸失敗。

3、資料轉存不能做到實時,沒有資料庫連線守護程序,只能重連一定次數,如果資料庫連線可能斷開,需要另外的補償機制。

4、本文中完成了在同一表中查詢,可以輸入postgresql關係型資料庫中聯表查詢的結果,保證適當的冗餘,建立合適的索引。

相關文章