RDS 觸發器eventFormat 爲 protobuf 的代碼使用示例

前言

函數計算發佈了新的觸發器-- RDS 觸發器,這標誌着函數計算的事件源新增加了一名成員 -- 阿里雲關係型數據庫( Relational Database Service,簡稱 RDS), 根據官方文檔的示例,只有 eventFormat 爲 json 的示例,本文作爲補充, 講解 eventFormat 爲 protobuf 時的代碼示例。

protobuf 格式

syntax = "proto3";
package protocol;
enum DBType {
  MySQL = 0;
  Redis = 1;
  Mongo = 2;
  HBase = 3;
}
message Message {
  //消費該message後可以ack的offset.考慮進行編碼.
  int64 offset = 1;
  //該message後可以ack的record對應的timestamp
  int64 timestamp = 2;
  //留作備用:以後傳送大的數據行可以拿來使用.
  int32 spare_flag = 3;
  int32 spare_seq = 4;
  //message的version
  int32 version = 5;
  //數據源
  DBType db_type = 6;
  //數據行
  repeated Entry entries = 7;
}
//操作
enum OpType {
  UNKOWN_TYPE = 0;
  BEGIN = 1;
  COMMIT = 2;
  //不在下列DDL操作用的query
  QUERY = 3;
  INSERT = 4;
  UPDATE = 5;
  DELETE = 6;
  CREATE = 7;
  ALTER = 8;
  DROP = 9;
  TRUNCATE = 10;
  RENAME = 11;
  //CREATE INDEX
  CINDEX = 12;
  //DROP INDEX
  DINDEX = 13;
  OPTIMIZE = 14;
  XA = 15;
}
message Entry {
  OpType operation = 1;
  //時間戳,單位s
  int64 timestamp = 2;
  //Transaction id
  string id = 3;
  //一個事務中的第幾行
  int64 sequence = 4;
  //DML操作的db_name,DDL操作時候session的默認db
  string db_name = 5;
  //DML操作的table_name
  string table_name = 6;
  //after image,操作的後鏡像.
  repeated Field row = 7;
  //before image,操作的前鏡像
  repeated Field before_row = 8;
  //非DML語句的sql
  string query = 9;
}
message Field {
  //column name
  string name = 1;
  //字符集
  string charset = 3;
  //第幾列
  int32 idx = 2;
  //對應java中的type
  int32 type_num = 4;
  //對於mysql,mysql中的type num;
  int32 org_type = 5;
  //在db中原始type的name
  string org_type_name = 6;
  //預留的flag
  int32 flag = 7;
  //是否爲NULL
  bool is_null = 8;
  //是否是pk
  bool is_pk = 9;
  //是否是unsigned value
  bool is_unsigned = 10;
  //是否是timestamp value(timestamp展示值和時區相關,這裏記錄標準時區的值)
  bool is_timestamp = 11;
  //value的值都用bytes表示,消費端需要先用charset結合bytes生成對應string.然後再轉換爲type_num對應的type value.
  //同時當charset爲空,即表示原數據類型就是binary類型
  bytes value = 12;
}

代碼示例

完整的代碼示例請下載本文最後的附件, 包含 3種runtime( python, php, nodejs)的使用案例, 下面展示各自使用的代碼簡短示例。

java runtime 示例請參考:Redis緩存淘汰

python

# -*- coding: utf-8 -*-

from proto import rdsEvent_pb2

bin_data = b""
# local data only for test
with open('./proto.bin', 'rb') as f:
   bin_data = f.read()

def handler(event, context):
    target = rdsEvent_pb2.Message()
    target.ParseFromString(event)
    #target.ParseFromString(bin_data)
    print(target.offset, target.db_type)
    entry = target.entries[0]
    print(entry.operation, entry.db_name, entry.table_name)
    print(entry.row[0].name, entry.row[1].value, entry.row[2].type_num)
    
    return "OK"

nodejs

'use strict';

var fs = require("fs");
var protobuf = require("protobufjs");

module.exports.handler = function(event, context, callback) {
    protobuf.load("rdsEvent.proto", function(err, root) {
        if (err)
            throw err;

        var rdsEventMessage = root.lookupType("proto.Message");
        
        // local data only for test
        //var event = fs.readFileSync('proto.bin');

        var message = rdsEventMessage.decode(event);

        console.log(JSON.stringify(message))
        callback(null, 'hello world');

    });
};

php

<?php

require_once __DIR__ . '/Proto/Field.php';
require_once __DIR__ . '/Proto/DBType.php';
require_once __DIR__ . '/Proto/OpType.php';
require_once __DIR__ . '/Proto/Entry.php';
require_once __DIR__ . '/Proto/Message.php';
require_once __DIR__ . '/GPBMetadata/RdsEvent.php';

// local data only for test
$filename = __DIR__ . "/proto.bin";
$handle = fopen($filename, "rb");
$data   = fread($handle, filesize($filename));
fclose($handle);

function handler($event, $context) {
    $res = new \Proto\Message();
    //$res->mergeFromString($data);
    $res->mergeFromString($event);
    echo $res->getDbType() . PHP_EOL;
    echo $res->getOffset() . PHP_EOL;
    echo $res->getEntries()[0]->getTableName() . PHP_EOL;
    return "ok";
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章