風控系統之事件溯源,決策流程記錄與版本控制

wnhyang發表於2024-08-29

個人部落格:無奈何楊(wnhyang)

個人語雀:wnhyang

共享語雀:線上知識共享

Github:wnhyang - Overview


背景

一天,小明在風控管理臺檢視事件資料時,發現一筆決策結果為“拒絕”❌的交易事件,小明點開事件詳情發現其觸發了一條“24小時內向不同陌生賬戶轉賬超過30w”的規則,規則設定的處置方式是“拒絕”❌。小明透過策略規則卻查不到那條“24小時內向不同陌生賬戶轉賬超過30w”的規則,經確認原來是這條規則在此交易觸發後一段時間內被修改了,已經不知道當時是如何配置的!?

這該怎麼辦?

我們要知道風控等其他系統都需要對於配置實時生效,所以使用了規則引擎,規則引擎具有實時生效優雅熱重新整理的特性,但也因此,如果規則設定有問題而沒有回滾/溯源/復現的機制,將是很大的問題!!!

所以本質上就是要在規則引擎應用之上打造完善的版本控制,能夠對規則歷史進行溯源。

事件記錄

之前的文章風控系統建設,指標策略規則流程設計,LiteFlow隱式子流程,構造EL和Chain,提到了最終儲存在es中大概有哪些資料。以下僅供參考,有部分還沒做。

這裡再次梳理一下:

1、基礎資料,保留所有事件欄位。

2、事件處理流程,也就是輸入的資料經歷了哪些流程和元件處理!

3、策略集結果,包括策略集、策略、規則的所有決策結果。還要加上特殊配置的策略執行流程。

4、指標資料,本次事件計算的所有指標資料。

{
  "result": {
    "name": "手機登入策略",
    "code": "phone_login",
    "disposalName": "透過",
    "disposalCode": "pass",
    "policyResults": [
      {
        "name": "手機登入最壞",
        "code": "phone_login_worst",
        "mode": "worst",
        "disposalName": "透過",
        "disposalCode": "pass",
        "ruleResults": [
          {
            "name": "測試規則03",
            "code": "352452",
            "disposalName": "透過",
            "disposalCode": "pass",
            "score": 0
          }
        ],
        "mockRuleResults": [

        ]
      },
      {
        "name": "手機登入順序",
        "code": "phone_login_order",
        "mode": "order",
        "disposalName": "透過",
        "disposalCode": "pass",
        "ruleResults": [

        ],
        "mockRuleResults": [

        ]
      }
    ]
  },
  "zbs": [{"id":"1","name":"24小時交易金額之和","type":"sum","version":0,"value":"1413.07938"},{"id":"3","name":"選必於","type":"sum","version":0,"value":"436864.3324399999"},{"id":"4","name":"24小時交易金額大於10萬求和","type":"sum","version":0,"value":"1413.07938"},{"id":"5","name":"規支才公照還","type":"ass","version":0,"value":"1.0"},{"id":"6","name":"且者礦","type":"max","version":0,"value":"988.56238"},{"id":"7","name":"北在文地","type":"min","version":0,"value":"424.517"},{"id":"8","name":"看活歷地許","type":"avg","version":0,"value":"706.53969"},{"id":"9","name":"情性特問寫養八","type":"sum","version":0,"value":"1413.07938"},{"id":"10","name":"其斷子把酸","type":"count","version":0,"value":"2.0"}],
  "fields": {
    "N_S_ipCity": "南昌市",
    "N_S_lonAndLat": "98.63974,12.4825",
    "N_S_payerType": "關在那邊員",
    "N_S_idCardCity": "未知",
    "N_S_payeeIDNumber": "640000198102131788",
    "N_S_ipProvince": "江西省",
    "N_S_payeeIDCountryRegion": "US",
    "N_F_transAmount": 424.517,
    "N_S_payerAddress": "其它區 山西省 承德市",
    "N_S_seqId": "c678bfbfb4c544eaaeb52373702a0aca",
    "N_S_payeePhoneNumber": "18643006812",
    "N_S_transSerialNo": "809bbad3-1c81-4b59-9e42-fa0b028d1448",
    "N_S_payerAccount": "1234567890",
    "N_S_payeeAccount": "1234567880",
    "N_S_ip": "106.230.80.158",
    "N_S_policyCode": "phone_login_worst",
    "N_S_payeeType": "濟常準屬適",
    "N_S_payerIDNumber": "420000199805245558",
    "N_S_payeeBankName": "ABC Bank",
    "N_S_phoneNumberProvince": "未知",
    "N_S_ipIsp": "電信",
    "N_S_payerIDCountryRegion": "US",
    "N_D_transTime": "2013-06-21 16:30:09",
    "N_S_phoneNumberCity": "成都",
    "N_S_phoneNumberIsp": "中國電信",
    "N_S_payeeAddress": "- 福建省 撫州市",
    "N_S_payeeRiskRating": "HIGH",
    "N_S_policySetCode": "phone_login",
    "N_S_payerBankName": "XYZ Bank",
    "N_S_idCardDistrict": "未知",
    "N_S_appName": "phone",
    "N_S_idCardProvince": "湖北省",
    "N_S_ipCountry": "中國",
    "N_S_payeeName": "範明",
    "N_S_payerName": "石娜",
    "N_S_payerPhoneNumber": "18123341918",
    "N_S_payerRiskRating": "HIGH"
  }
}

以下僅是示例,表示一筆事件要記錄當時處理流程,示例是線性簡單的流程,但實際上怎麼樣,不知道呢🤷

image

這樣每次事件都具備了溯源的基礎了,相當於對於當時場景拍了照片(快照嘛)。但是有了照片怎麼找到照片裡的人呢?🥺

請安心,隨著時間的變化,照片里人早已變了模樣,只能試著找找嘍。

版本控制

這就要提到一種主表+歷史表(或者講快照表)的設計,這種設計特別適用於需要跟蹤資料變更的場景。

1. 主表 (Master Table)

主表儲存的是最新的、有效的資料記錄。通常情況下,主表中會包含業務關鍵欄位以及一些基本的後設資料資訊(如建立時間、最後修改時間等)。

示例欄位

  • id:唯一標識
  • name:名稱
  • status:狀態
  • created_at:建立時間
  • updated_at:更新時間

2. 歷史表 (History Table)

歷史表則用來儲存所有歷史版本的資料記錄。每當主表中的資料發生變化時,舊的資料會被複制到歷史表中,以便長期儲存。

示例欄位

  • id:唯一標識
  • master_id:與主表中的ID對應
  • name:名稱
  • status:狀態
  • version:版本號
  • changed_by:變更操作者
  • created_at:建立時間
  • updated_at:更新時間

上面是大致的思路,具體怎麼實現還是取決於具體的業務場景。

在使用LiteFlow的情況下版本控制又要複雜一些,這裡僅提供思路。

關於風控系統中變化最多的規則配置,先來評估一下資料量。已知策略集-策略-規則,策略集對策略是1-n,策略對規則也是1-n,那麼對應資料是$$n^{2}$$。如果n100100條規則也不是很誇張🙂‍↕️),那麼一個版本的規則庫就有1w條資料,任意修改變更一次,一年變化100次也不多對吧🙄,那麼歷史表就要再✖️100,也就是100w,好像有點難頂了!

怎麼辦呢?

不想資料行過多的話就降維打擊吧🤔

主表可以設定為`1-n-$$n^{2}$$,但歷史表可以簡化一下,降一個緯度。

history歷史表可以設定欄位:

  • id:主鍵
  • policy_set_id:策略集id
  • policy_set_name:策略集名
  • policy_id:策略id
  • policy_name:策略名
  • version:版本號
  • changed_by:變更操作者
  • created_at:建立時間
  • updated_at:更新時間

具體的策略對應的資訊進行垂直拆分,

history_ext歷史擴充套件表設定欄位:

  • id:與歷史表一致
  • policy_info:策略資訊json字串
  • rule_info:規則資訊json字串

這樣的話其實就是將策略-規則透過json串壓縮在一張表裡了,不再是1-n了。

這樣的還有一點注意,status如何定義。

  • 如果主表表示最新資料,那麼主表就是執行區,status應該是表示開關等,只有大的修改後才會進入歷史表,歷史表最新版本資料不包含主表資料,。
  • 如果歷史表最新版本表示最新資料,那麼歷史表status就有historyonline之分,主表就表示工作區,狀態是等待提交、已提交,類似於git工作區。

image

寫在最後

拙作艱辛,字句心血,望諸君垂青,多予支援,不勝感激。


個人部落格:無奈何楊(wnhyang)

個人語雀:wnhyang

共享語雀:線上知識共享

Github:wnhyang - Overview

相關文章